Merge branch 'master' of 192.168.0.100:/repos/git/asterisk
This commit is contained in:
commit
b7347a56f8
12
CHANGES
12
CHANGES
|
@ -65,6 +65,18 @@ libpri channel driver (chan_dahdi) DAHDI changes
|
|||
application when the option is enabled.
|
||||
* Added mcid_send option to allow sending a MCID request on a span.
|
||||
|
||||
Calendaring
|
||||
--------------------------
|
||||
* Added setvar option to calendar.conf to allow setting channel variables on
|
||||
notification channels.
|
||||
|
||||
MixMonitor
|
||||
--------------------------
|
||||
* Added two new options, r and t with file name arguments to record
|
||||
single direction (unmixed) audio recording separate from the bidirectional
|
||||
(mixed) recording. The mixed file name argument is optional now as long
|
||||
as at least one recording option is used.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
--- Functionality changes from Asterisk 1.6.2 to Asterisk 1.8 ----------------
|
||||
------------------------------------------------------------------------------
|
||||
|
|
14
Makefile
14
Makefile
|
@ -223,8 +223,12 @@ ifneq ($(findstring BSD,$(OSARCH)),)
|
|||
endif
|
||||
|
||||
ifeq ($(findstring -march,$(_ASTCFLAGS) $(ASTCFLAGS)),)
|
||||
ifneq ($(PROC),ultrasparc)
|
||||
_ASTCFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
ifneq ($(AST_MARCH_NATIVE),)
|
||||
_ASTCFLAGS+=$(AST_MARCH_NATIVE)
|
||||
else
|
||||
ifneq ($(PROC),ultrasparc)
|
||||
_ASTCFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -233,8 +237,10 @@ ifeq ($(PROC),ppc)
|
|||
endif
|
||||
|
||||
ifeq ($(OSARCH),FreeBSD)
|
||||
ifeq ($(PROC),i386)
|
||||
_ASTCFLAGS+=-march=i686
|
||||
ifeq ($(findstring -march,$(_ASTCFLAGS) $(ASTCFLAGS)),)
|
||||
ifeq ($(PROC),i386)
|
||||
_ASTCFLAGS+=-march=i686
|
||||
endif
|
||||
endif
|
||||
# -V is understood by BSD Make, not by GNU make.
|
||||
BSDVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk)
|
||||
|
|
|
@ -72,6 +72,15 @@ From 1.6.2 to 1.8:
|
|||
The new channel naming for PRI channels is:
|
||||
DAHDI/i<span>/<number>[:<subaddress>]-<sequence-number>
|
||||
|
||||
* Added CHANNEL(dahdi_span), CHANNEL(dahdi_channel), and CHANNEL(dahdi_type)
|
||||
so the dialplan can determine the B channel currently in use by the channel.
|
||||
Use CHANNEL(no_media_path) to determine if the channel even has a B channel.
|
||||
|
||||
* Added AMI event DAHDIChannel to associate a DAHDI channel with an Asterisk
|
||||
channel so AMI applications can passively determine the B channel currently
|
||||
in use. Calls with "no-media" as the DAHDIChannel do not have an associated
|
||||
B channel. No-media calls are either on hold or call-waiting.
|
||||
|
||||
* The ChanIsAvail application has been changed so the AVAILSTATUS variable
|
||||
no longer contains both the device state and cause code. The cause code
|
||||
is now available in the AVAILCAUSECODE variable. If existing dialplan logic
|
||||
|
|
|
@ -520,6 +520,7 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
|
|||
}
|
||||
|
||||
ast_udptl_set_error_correction_scheme(pvt->udptl, UDPTL_ERROR_CORRECTION_NONE);
|
||||
ast_udptl_set_far_max_datagram(pvt->udptl, 144);
|
||||
pvt->faxmode = 0;
|
||||
pvt->t38support = gT38Support;
|
||||
pvt->rtptimeout = gRTPTimeout;
|
||||
|
@ -4158,11 +4159,14 @@ void setup_udptl_connection(ooCallData *call, const char *remoteIp,
|
|||
them.sin_port = htons(remotePort);
|
||||
ast_sockaddr_from_sin(&them_addr, &them);
|
||||
ast_udptl_set_peer(p->udptl, &them_addr);
|
||||
ast_udptl_set_tag(p->udptl, "%s", p->owner->name);
|
||||
p->t38_tx_enable = 1;
|
||||
p->lastTxT38 = time(NULL);
|
||||
if (p->t38support == T38_ENABLED) {
|
||||
struct ast_control_t38_parameters parameters = { .request_response = 0 };
|
||||
parameters.request_response = AST_T38_NEGOTIATED;
|
||||
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
||||
parameters.rate = AST_T38_RATE_14400;
|
||||
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters));
|
||||
}
|
||||
if (gH323Debug)
|
||||
|
@ -4357,6 +4361,16 @@ void onModeChanged(ooCallData *call, int t38mode) {
|
|||
|
||||
struct ast_control_t38_parameters parameters = { .request_response = 0 };
|
||||
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
|
||||
if (call->T38FarMaxDatagram) {
|
||||
ast_udptl_set_far_max_datagram(p->udptl, call->T38FarMaxDatagram);
|
||||
} else {
|
||||
ast_udptl_set_far_max_datagram(p->udptl, 144);
|
||||
}
|
||||
if (call->T38Version) {
|
||||
parameters.version = call->T38Version;
|
||||
}
|
||||
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
||||
parameters.rate = AST_T38_RATE_14400;
|
||||
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS,
|
||||
¶meters, sizeof(parameters));
|
||||
p->faxmode = 1;
|
||||
|
@ -4366,6 +4380,8 @@ void onModeChanged(ooCallData *call, int t38mode) {
|
|||
if (p->t38support == T38_ENABLED) {
|
||||
struct ast_control_t38_parameters parameters = { .request_response = 0 };
|
||||
parameters.request_response = AST_T38_REQUEST_TERMINATE;
|
||||
parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
|
||||
parameters.rate = AST_T38_RATE_14400;
|
||||
ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS,
|
||||
¶meters, sizeof(parameters));
|
||||
}
|
||||
|
|
|
@ -214,6 +214,8 @@ typedef struct OOH323CallData {
|
|||
ASN1UINT8 requestSequence;
|
||||
ASN1UINT reqFlags;
|
||||
ASN1UINT t38sides;
|
||||
int T38FarMaxDatagram;
|
||||
int T38Version;
|
||||
H235TimeStamp alertingTime, connectTime, endTime; /* time data for gatekeeper */
|
||||
FastStartResponse *pFastStartRes; /* fast start response */
|
||||
struct OOH323Regex* rtpMask;
|
||||
|
|
|
@ -2710,6 +2710,12 @@ int ooAddRemoteDataApplicationCapability(OOH323CallData *call,
|
|||
switch(dataCap->application.t)
|
||||
{
|
||||
case T_H245DataApplicationCapability_application_t38fax:
|
||||
if (dataCap->application.u.t38fax->t38FaxProfile.m.t38FaxUdpOptionsPresent) {
|
||||
call->T38FarMaxDatagram = dataCap->application.u.t38fax->t38FaxProfile.t38FaxUdpOptions.t38FaxMaxDatagram;
|
||||
}
|
||||
if (dataCap->application.u.t38fax->t38FaxProfile.m.versionPresent) {
|
||||
call->T38Version = dataCap->application.u.t38fax->t38FaxProfile.version;
|
||||
}
|
||||
return ooCapabilityAddT38Capability(call, OO_T38,
|
||||
dir, NULL, NULL, NULL, NULL,TRUE);
|
||||
default:
|
||||
|
|
|
@ -710,6 +710,7 @@ static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
|
|||
struct ast_autochan *autochan, struct ast_channel *chan)
|
||||
{
|
||||
struct ast_channel *next;
|
||||
struct ast_autochan *autochan_store;
|
||||
const size_t pseudo_len = strlen("DAHDI/pseudo");
|
||||
|
||||
if (!iter) {
|
||||
|
@ -727,7 +728,10 @@ redo:
|
|||
goto redo;
|
||||
}
|
||||
|
||||
return ast_autochan_setup(next);
|
||||
autochan_store = ast_autochan_setup(next);
|
||||
ast_channel_unref(next);
|
||||
|
||||
return autochan_store;
|
||||
}
|
||||
|
||||
static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
|
||||
|
|
287
apps/app_dial.c
287
apps/app_dial.c
|
@ -135,12 +135,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
</option>
|
||||
<option name="f">
|
||||
<argument name="x" required="false" />
|
||||
<para>If <replaceable>x</replaceable> is not provided, force the callerid of the <emphasis>calling</emphasis>
|
||||
channel to be set as the extension associated with the channel using a dialplan <literal>hint</literal>.
|
||||
<para>If <replaceable>x</replaceable> is not provided, force the CallerID sent on a call-forward or
|
||||
deflection to the dialplan extension of this Dial() using a dialplan <literal>hint</literal>.
|
||||
For example, some PSTNs do not allow CallerID to be set to anything
|
||||
other than the number assigned to the caller. If <replaceable>x</replaceable> is provided, though, then
|
||||
this option behaves quite differently. Any outgoing channel created will have its connected party information
|
||||
set to <replaceable>x</replaceable></para>
|
||||
other than the numbers assigned to you.
|
||||
If <replaceable>x</replaceable> is provided, force the CallerID sent to <replaceable>x</replaceable>.</para>
|
||||
</option>
|
||||
<option name="F" argsep="^">
|
||||
<argument name="context" required="false" />
|
||||
|
@ -296,9 +295,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
that if Caller*ID is present, do not screen the call.</para>
|
||||
</option>
|
||||
<option name="o">
|
||||
<para>Specify that the Caller*ID that was present on the <emphasis>calling</emphasis> channel
|
||||
be set as the Caller*ID on the <emphasis>called</emphasis> channel. This was the
|
||||
behavior of Asterisk 1.0 and earlier.</para>
|
||||
<argument name="x" required="false" />
|
||||
<para>If <replaceable>x</replaceable> is not provided, specify that the CallerID that was present on the
|
||||
<emphasis>calling</emphasis> channel be stored as the CallerID on the <emphasis>called</emphasis> channel.
|
||||
This was the behavior of Asterisk 1.0 and earlier.
|
||||
If <replaceable>x</replaceable> is provided, specify the CallerID stored on the <emphasis>called</emphasis> channel.
|
||||
Note that o(${CALLERID(all)}) is similar to option o without the parameter.</para>
|
||||
</option>
|
||||
<option name="O">
|
||||
<argument name="mode">
|
||||
|
@ -338,7 +340,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
</option>
|
||||
<option name="s">
|
||||
<argument name="x" required="true" />
|
||||
<para>Force the outgoing callerid tag parameter to be set to the string <replaceable>x</replaceable></para>
|
||||
<para>Force the outgoing callerid tag parameter to be set to the string <replaceable>x</replaceable>.</para>
|
||||
<para>Works with the f option.</para>
|
||||
</option>
|
||||
<option name="t">
|
||||
<para>Allow the called party to transfer the calling party by sending the
|
||||
|
@ -403,6 +406,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
<literal>prohib</literal>
|
||||
<literal>unavailable</literal></para>
|
||||
</argument>
|
||||
<para>Works with the f option.</para>
|
||||
</option>
|
||||
<option name="w">
|
||||
<para>Allow the called party to enable recording of the call by sending
|
||||
|
@ -574,6 +578,7 @@ enum {
|
|||
OPT_ARG_DURATION_STOP,
|
||||
OPT_ARG_OPERMODE,
|
||||
OPT_ARG_SCREEN_NOINTRO,
|
||||
OPT_ARG_ORIGINAL_CLID,
|
||||
OPT_ARG_FORCECLID,
|
||||
OPT_ARG_FORCE_CID_TAG,
|
||||
OPT_ARG_FORCE_CID_PRES,
|
||||
|
@ -604,7 +609,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
|
|||
AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
|
||||
AST_APP_OPTION_ARG('n', OPT_SCREEN_NOINTRO, OPT_ARG_SCREEN_NOINTRO),
|
||||
AST_APP_OPTION('N', OPT_SCREEN_NOCALLERID),
|
||||
AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
|
||||
AST_APP_OPTION_ARG('o', OPT_ORIGINAL_CLID, OPT_ARG_ORIGINAL_CLID),
|
||||
AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
|
||||
AST_APP_OPTION('p', OPT_SCREENING),
|
||||
AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
|
||||
|
@ -792,7 +797,8 @@ static void senddialendevent(struct ast_channel *src, const char *dialstatus)
|
|||
* \todo eventually this function should be intergrated into and replaced by ast_call_forward()
|
||||
*/
|
||||
static void do_forward(struct chanlist *o,
|
||||
struct cause_args *num, struct ast_flags64 *peerflags, int single, int *to)
|
||||
struct cause_args *num, struct ast_flags64 *peerflags, int single, int *to,
|
||||
struct ast_party_id *forced_clid, struct ast_party_id *stored_clid)
|
||||
{
|
||||
char tmpchan[256];
|
||||
struct ast_channel *original = o->chan;
|
||||
|
@ -801,6 +807,7 @@ static void do_forward(struct chanlist *o,
|
|||
char *stuff;
|
||||
char *tech;
|
||||
int cause;
|
||||
struct ast_party_caller caller;
|
||||
|
||||
ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
|
||||
if ((stuff = strchr(tmpchan, '/'))) {
|
||||
|
@ -878,17 +885,34 @@ static void do_forward(struct chanlist *o,
|
|||
|
||||
c->dialed.transit_network_select = in->dialed.transit_network_select;
|
||||
|
||||
if (ast_test_flag64(o, OPT_FORCECLID)) {
|
||||
ast_party_id_free(&c->caller.id);
|
||||
ast_party_id_init(&c->caller.id);
|
||||
c->caller.id.number.valid = 1;
|
||||
c->caller.id.number.str = ast_strdup(S_OR(in->macroexten, in->exten));
|
||||
ast_string_field_set(c, accountcode, c->accountcode);
|
||||
} else {
|
||||
ast_party_caller_copy(&c->caller, &in->caller);
|
||||
ast_string_field_set(c, accountcode, in->accountcode);
|
||||
/* Determine CallerID to store in outgoing channel. */
|
||||
ast_party_caller_set_init(&caller, &c->caller);
|
||||
if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
|
||||
caller.id = *stored_clid;
|
||||
ast_channel_set_caller_event(c, &caller, NULL);
|
||||
} else if (ast_strlen_zero(S_COR(c->caller.id.number.valid,
|
||||
c->caller.id.number.str, NULL))) {
|
||||
/*
|
||||
* The new channel has no preset CallerID number by the channel
|
||||
* driver. Use the dialplan extension and hint name.
|
||||
*/
|
||||
caller.id = *stored_clid;
|
||||
ast_channel_set_caller_event(c, &caller, NULL);
|
||||
}
|
||||
ast_party_connected_line_copy(&c->connected, &original->connected);
|
||||
|
||||
/* Determine CallerID for outgoing channel to send. */
|
||||
if (ast_test_flag64(o, OPT_FORCECLID)) {
|
||||
struct ast_party_connected_line connected;
|
||||
|
||||
ast_party_connected_line_init(&connected);
|
||||
connected.id = *forced_clid;
|
||||
ast_party_connected_line_copy(&c->connected, &connected);
|
||||
} else {
|
||||
ast_connected_line_copy_from_caller(&c->connected, &in->caller);
|
||||
}
|
||||
|
||||
ast_string_field_set(c, accountcode, in->accountcode);
|
||||
|
||||
c->appl = "AppDial";
|
||||
c->data = "(Outgoing Line)";
|
||||
/*
|
||||
|
@ -925,17 +949,8 @@ static void do_forward(struct chanlist *o,
|
|||
CHANNEL_DEADLOCK_AVOIDANCE(c);
|
||||
}
|
||||
senddialevent(in, c, stuff);
|
||||
if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
|
||||
char cidname[AST_MAX_EXTENSION] = "";
|
||||
const char *tmpexten;
|
||||
tmpexten = ast_strdupa(S_OR(in->macroexten, in->exten));
|
||||
ast_channel_unlock(in);
|
||||
ast_channel_unlock(c);
|
||||
ast_set_callerid(c, tmpexten, get_cid_name(cidname, sizeof(cidname), in), NULL);
|
||||
} else {
|
||||
ast_channel_unlock(in);
|
||||
ast_channel_unlock(c);
|
||||
}
|
||||
ast_channel_unlock(in);
|
||||
ast_channel_unlock(c);
|
||||
/* Hangup the original channel now, in case we needed it */
|
||||
ast_hangup(original);
|
||||
}
|
||||
|
@ -959,7 +974,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
|
|||
char *opt_args[],
|
||||
struct privacy_args *pa,
|
||||
const struct cause_args *num_in, int *result, char *dtmf_progress,
|
||||
const int ignore_cc)
|
||||
const int ignore_cc,
|
||||
struct ast_party_id *forced_clid, struct ast_party_id *stored_clid)
|
||||
{
|
||||
struct cause_args num = *num_in;
|
||||
int prestart = num.busy + num.congestion + num.nochan;
|
||||
|
@ -1104,7 +1120,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
|
|||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
do_forward(o, &num, peerflags, single, to);
|
||||
do_forward(o, &num, peerflags, single, to, forced_clid, stored_clid);
|
||||
continue;
|
||||
}
|
||||
f = ast_read(winner);
|
||||
|
@ -1814,7 +1830,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
struct cause_args num = { chan, 0, 0, 0 };
|
||||
int cause;
|
||||
char numsubst[256];
|
||||
char *cid_num = NULL, *cid_name = NULL, *cid_tag = NULL, *cid_pres = NULL;
|
||||
|
||||
struct ast_bridge_config config = { { 0, } };
|
||||
struct timeval calldurationlimit = { 0, };
|
||||
|
@ -1842,6 +1857,29 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
int fulldial = 0, num_dialed = 0;
|
||||
int ignore_cc = 0;
|
||||
char device_name[AST_CHANNEL_NAME];
|
||||
char forced_clid_name[AST_MAX_EXTENSION];
|
||||
char stored_clid_name[AST_MAX_EXTENSION];
|
||||
int force_forwards_only; /*!< TRUE if force CallerID on call forward only. Legacy behaviour.*/
|
||||
/*!
|
||||
* \brief Forced CallerID party information to send.
|
||||
* \note This will not have any malloced strings so do not free it.
|
||||
*/
|
||||
struct ast_party_id forced_clid;
|
||||
/*!
|
||||
* \brief Stored CallerID information if needed.
|
||||
*
|
||||
* \note If OPT_ORIGINAL_CLID set then this is the o option
|
||||
* CallerID. Otherwise it is the dialplan extension and hint
|
||||
* name.
|
||||
*
|
||||
* \note This will not have any malloced strings so do not free it.
|
||||
*/
|
||||
struct ast_party_id stored_clid;
|
||||
/*!
|
||||
* \brief CallerID party information to store.
|
||||
* \note This will not have any malloced strings so do not free it.
|
||||
*/
|
||||
struct ast_party_caller caller;
|
||||
|
||||
/* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
|
||||
pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
|
||||
|
@ -1915,12 +1953,94 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (ast_test_flag64(&opts, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID]))
|
||||
ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &cid_name, &cid_num);
|
||||
if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG]))
|
||||
cid_tag = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_TAG]);
|
||||
if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES) && !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES]))
|
||||
cid_pres = ast_strdupa(opt_args[OPT_ARG_FORCE_CID_PRES]);
|
||||
/* Setup the forced CallerID information to send if used. */
|
||||
ast_party_id_init(&forced_clid);
|
||||
force_forwards_only = 0;
|
||||
if (ast_test_flag64(&opts, OPT_FORCECLID)) {
|
||||
if (ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) {
|
||||
ast_channel_lock(chan);
|
||||
forced_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten));
|
||||
ast_channel_unlock(chan);
|
||||
forced_clid_name[0] = '\0';
|
||||
forced_clid.name.str = (char *) get_cid_name(forced_clid_name,
|
||||
sizeof(forced_clid_name), chan);
|
||||
force_forwards_only = 1;
|
||||
} else {
|
||||
/* Note: The opt_args[OPT_ARG_FORCECLID] string value is altered here. */
|
||||
ast_callerid_parse(opt_args[OPT_ARG_FORCECLID], &forced_clid.name.str,
|
||||
&forced_clid.number.str);
|
||||
}
|
||||
if (!ast_strlen_zero(forced_clid.name.str)) {
|
||||
forced_clid.name.valid = 1;
|
||||
}
|
||||
if (!ast_strlen_zero(forced_clid.number.str)) {
|
||||
forced_clid.number.valid = 1;
|
||||
}
|
||||
}
|
||||
if (ast_test_flag64(&opts, OPT_FORCE_CID_TAG)
|
||||
&& !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_TAG])) {
|
||||
forced_clid.tag = opt_args[OPT_ARG_FORCE_CID_TAG];
|
||||
}
|
||||
forced_clid.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
|
||||
if (ast_test_flag64(&opts, OPT_FORCE_CID_PRES)
|
||||
&& !ast_strlen_zero(opt_args[OPT_ARG_FORCE_CID_PRES])) {
|
||||
int pres;
|
||||
|
||||
pres = ast_parse_caller_presentation(opt_args[OPT_ARG_FORCE_CID_PRES]);
|
||||
if (0 <= pres) {
|
||||
forced_clid.number.presentation = pres;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the stored CallerID information if needed. */
|
||||
ast_party_id_init(&stored_clid);
|
||||
if (ast_test_flag64(&opts, OPT_ORIGINAL_CLID)) {
|
||||
if (ast_strlen_zero(opt_args[OPT_ARG_ORIGINAL_CLID])) {
|
||||
ast_channel_lock(chan);
|
||||
ast_party_id_set_init(&stored_clid, &chan->caller.id);
|
||||
if (!ast_strlen_zero(chan->caller.id.name.str)) {
|
||||
stored_clid.name.str = ast_strdupa(chan->caller.id.name.str);
|
||||
}
|
||||
if (!ast_strlen_zero(chan->caller.id.number.str)) {
|
||||
stored_clid.number.str = ast_strdupa(chan->caller.id.number.str);
|
||||
}
|
||||
if (!ast_strlen_zero(chan->caller.id.subaddress.str)) {
|
||||
stored_clid.subaddress.str = ast_strdupa(chan->caller.id.subaddress.str);
|
||||
}
|
||||
if (!ast_strlen_zero(chan->caller.id.tag)) {
|
||||
stored_clid.tag = ast_strdupa(chan->caller.id.tag);
|
||||
}
|
||||
ast_channel_unlock(chan);
|
||||
} else {
|
||||
/* Note: The opt_args[OPT_ARG_ORIGINAL_CLID] string value is altered here. */
|
||||
ast_callerid_parse(opt_args[OPT_ARG_ORIGINAL_CLID], &stored_clid.name.str,
|
||||
&stored_clid.number.str);
|
||||
if (!ast_strlen_zero(stored_clid.name.str)) {
|
||||
stored_clid.name.valid = 1;
|
||||
}
|
||||
if (!ast_strlen_zero(stored_clid.number.str)) {
|
||||
stored_clid.number.valid = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* In case the new channel has no preset CallerID number by the
|
||||
* channel driver, setup the dialplan extension and hint name.
|
||||
*/
|
||||
stored_clid_name[0] = '\0';
|
||||
stored_clid.name.str = (char *) get_cid_name(stored_clid_name,
|
||||
sizeof(stored_clid_name), chan);
|
||||
if (ast_strlen_zero(stored_clid.name.str)) {
|
||||
stored_clid.name.str = NULL;
|
||||
} else {
|
||||
stored_clid.name.valid = 1;
|
||||
}
|
||||
ast_channel_lock(chan);
|
||||
stored_clid.number.str = ast_strdupa(S_OR(chan->macroexten, chan->exten));
|
||||
stored_clid.number.valid = 1;
|
||||
ast_channel_unlock(chan);
|
||||
}
|
||||
|
||||
if (ast_test_flag64(&opts, OPT_RESETCDR) && chan->cdr)
|
||||
ast_cdr_reset(chan->cdr, NULL);
|
||||
if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
|
||||
|
@ -2094,47 +2214,50 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
tc->data = "(Outgoing Line)";
|
||||
memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
|
||||
|
||||
/* If the new channel has no callerid, try to guess what it should be */
|
||||
if (!tc->caller.id.number.valid) {
|
||||
if (chan->connected.id.number.valid) {
|
||||
struct ast_party_caller caller;
|
||||
|
||||
ast_party_caller_set_init(&caller, &tc->caller);
|
||||
caller.id = chan->connected.id;
|
||||
caller.ani = chan->connected.ani;
|
||||
ast_channel_set_caller_event(tc, &caller, NULL);
|
||||
} else if (!ast_strlen_zero(chan->dialed.number.str)) {
|
||||
ast_set_callerid(tc, chan->dialed.number.str, NULL, NULL);
|
||||
} else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) {
|
||||
ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL);
|
||||
}
|
||||
/* Determine CallerID to store in outgoing channel. */
|
||||
ast_party_caller_set_init(&caller, &tc->caller);
|
||||
if (ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
|
||||
caller.id = stored_clid;
|
||||
ast_channel_set_caller_event(tc, &caller, NULL);
|
||||
ast_set_flag64(tmp, DIAL_CALLERID_ABSENT);
|
||||
} else if (ast_strlen_zero(S_COR(tc->caller.id.number.valid,
|
||||
tc->caller.id.number.str, NULL))) {
|
||||
/*
|
||||
* The new channel has no preset CallerID number by the channel
|
||||
* driver. Use the dialplan extension and hint name.
|
||||
*/
|
||||
caller.id = stored_clid;
|
||||
if (!caller.id.name.valid
|
||||
&& !ast_strlen_zero(S_COR(chan->connected.id.name.valid,
|
||||
chan->connected.id.name.str, NULL))) {
|
||||
/*
|
||||
* No hint name available. We have a connected name supplied by
|
||||
* the dialplan we can use instead.
|
||||
*/
|
||||
caller.id.name = chan->connected.id.name;
|
||||
}
|
||||
ast_channel_set_caller_event(tc, &caller, NULL);
|
||||
ast_set_flag64(tmp, DIAL_CALLERID_ABSENT);
|
||||
} else if (ast_strlen_zero(S_COR(tc->caller.id.name.valid, tc->caller.id.name.str,
|
||||
NULL))) {
|
||||
/* The new channel has no preset CallerID name by the channel driver. */
|
||||
if (!ast_strlen_zero(S_COR(chan->connected.id.name.valid,
|
||||
chan->connected.id.name.str, NULL))) {
|
||||
/*
|
||||
* We have a connected name supplied by the dialplan we can
|
||||
* use instead.
|
||||
*/
|
||||
caller.id.name = chan->connected.id.name;
|
||||
ast_channel_set_caller_event(tc, &caller, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_test_flag64(peerflags, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) {
|
||||
/* Determine CallerID for outgoing channel to send. */
|
||||
if (ast_test_flag64(peerflags, OPT_FORCECLID) && !force_forwards_only) {
|
||||
struct ast_party_connected_line connected;
|
||||
int pres;
|
||||
|
||||
ast_party_connected_line_set_init(&connected, &tc->connected);
|
||||
if (cid_pres) {
|
||||
pres = ast_parse_caller_presentation(cid_pres);
|
||||
if (pres < 0) {
|
||||
pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
|
||||
}
|
||||
} else {
|
||||
pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
|
||||
}
|
||||
if (cid_num) {
|
||||
connected.id.number.valid = 1;
|
||||
connected.id.number.str = cid_num;
|
||||
connected.id.number.presentation = pres;
|
||||
}
|
||||
if (cid_name) {
|
||||
connected.id.name.valid = 1;
|
||||
connected.id.name.str = cid_name;
|
||||
connected.id.name.presentation = pres;
|
||||
}
|
||||
connected.id.tag = cid_tag;
|
||||
connected.id = forced_clid;
|
||||
ast_channel_set_connected_line(tc, &connected, NULL);
|
||||
} else {
|
||||
ast_connected_line_copy_from_caller(&tc->connected, &chan->caller);
|
||||
|
@ -2184,7 +2307,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
if (res) {
|
||||
/* Again, keep going even if there's an error */
|
||||
ast_debug(1, "ast call on peer returned %d\n", res);
|
||||
ast_verb(3, "Couldn't call %s\n", numsubst);
|
||||
ast_verb(3, "Couldn't call %s/%s\n", tech, numsubst);
|
||||
if (tc->hangupcause) {
|
||||
chan->hangupcause = tc->hangupcause;
|
||||
}
|
||||
|
@ -2195,14 +2318,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
chanlist_free(tmp);
|
||||
continue;
|
||||
} else {
|
||||
const char *tmpexten = ast_strdupa(S_OR(chan->macroexten, chan->exten));
|
||||
senddialevent(chan, tc, numsubst);
|
||||
ast_verb(3, "Called %s\n", numsubst);
|
||||
ast_verb(3, "Called %s/%s\n", tech, numsubst);
|
||||
ast_channel_unlock(chan);
|
||||
if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID)) {
|
||||
char cidname[AST_MAX_EXTENSION];
|
||||
ast_set_callerid(tc, tmpexten, get_cid_name(cidname, sizeof(cidname), chan), NULL);
|
||||
}
|
||||
}
|
||||
/* Put them in the list of outgoing thingies... We're ready now.
|
||||
XXX If we're forcibly removed, these outgoing calls won't get
|
||||
|
@ -2263,7 +2381,8 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||
}
|
||||
}
|
||||
|
||||
peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result, dtmf_progress, ignore_cc);
|
||||
peer = wait_for_answer(chan, outgoing, &to, peerflags, opt_args, &pa, &num, &result,
|
||||
dtmf_progress, ignore_cc, &forced_clid, &stored_clid);
|
||||
|
||||
/* The ast_channel_datastore_remove() function could fail here if the
|
||||
* datastore was moved to another channel during a masquerade. If this is
|
||||
|
|
|
@ -162,6 +162,7 @@ static void send_eivr_event(FILE *handle, const char event, const char *data,
|
|||
|
||||
fprintf(handle, "%s\n", ast_str_buffer(tmp));
|
||||
ast_debug(1, "sent '%s'\n", ast_str_buffer(tmp));
|
||||
ast_free(tmp);
|
||||
}
|
||||
|
||||
static void *gen_alloc(struct ast_channel *chan, void *params)
|
||||
|
|
|
@ -89,6 +89,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
of <replaceable>x</replaceable> (range <literal>-4</literal> to <literal>4</literal>)</para>
|
||||
<argument name="x" required="true" />
|
||||
</option>
|
||||
<option name="r">
|
||||
<argument name="file" required="true" />
|
||||
<para>Use the specified file to record the <emphasis>receive</emphasis> audio feed.
|
||||
Like with the basic filename argument, if an absolute path isn't given, it will create
|
||||
the file in the configured monitoring directory.</para>
|
||||
|
||||
</option>
|
||||
<option name="t">
|
||||
<argument name="file" required="true" />
|
||||
<para>Use the specified file to record the <emphasis>transmit</emphasis> audio feed.
|
||||
Like with the basic filename argument, if an absolute path isn't given, it will create
|
||||
the file in the configured monitoring directory.</para>
|
||||
</option>
|
||||
</optionlist>
|
||||
</parameter>
|
||||
<parameter name="command">
|
||||
|
@ -159,6 +172,8 @@ static const char * const mixmonitor_spy_type = "MixMonitor";
|
|||
struct mixmonitor {
|
||||
struct ast_audiohook audiohook;
|
||||
char *filename;
|
||||
char *filename_read;
|
||||
char *filename_write;
|
||||
char *post_process;
|
||||
char *name;
|
||||
unsigned int flags;
|
||||
|
@ -172,13 +187,18 @@ enum mixmonitor_flags {
|
|||
MUXFLAG_VOLUME = (1 << 3),
|
||||
MUXFLAG_READVOLUME = (1 << 4),
|
||||
MUXFLAG_WRITEVOLUME = (1 << 5),
|
||||
MUXFLAG_READ = (1 << 6),
|
||||
MUXFLAG_WRITE = (1 << 7),
|
||||
MUXFLAG_COMBINED = (1 << 8),
|
||||
};
|
||||
|
||||
enum mixmonitor_args {
|
||||
OPT_ARG_READVOLUME = 0,
|
||||
OPT_ARG_WRITEVOLUME,
|
||||
OPT_ARG_VOLUME,
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
OPT_ARG_WRITENAME,
|
||||
OPT_ARG_READNAME,
|
||||
OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
|
||||
};
|
||||
|
||||
AST_APP_OPTIONS(mixmonitor_opts, {
|
||||
|
@ -187,6 +207,8 @@ AST_APP_OPTIONS(mixmonitor_opts, {
|
|||
AST_APP_OPTION_ARG('v', MUXFLAG_READVOLUME, OPT_ARG_READVOLUME),
|
||||
AST_APP_OPTION_ARG('V', MUXFLAG_WRITEVOLUME, OPT_ARG_WRITEVOLUME),
|
||||
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
|
||||
AST_APP_OPTION_ARG('r', MUXFLAG_READ, OPT_ARG_READNAME),
|
||||
AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),
|
||||
});
|
||||
|
||||
struct mixmonitor_ds {
|
||||
|
@ -197,7 +219,11 @@ struct mixmonitor_ds {
|
|||
/* The filestream is held in the datastore so it can be stopped
|
||||
* immediately during stop_mixmonitor or channel destruction. */
|
||||
int fs_quit;
|
||||
|
||||
struct ast_filestream *fs;
|
||||
struct ast_filestream *fs_read;
|
||||
struct ast_filestream *fs_write;
|
||||
|
||||
struct ast_audiohook *audiohook;
|
||||
};
|
||||
|
||||
|
@ -207,11 +233,31 @@ struct mixmonitor_ds {
|
|||
*/
|
||||
static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds)
|
||||
{
|
||||
unsigned char quitting = 0;
|
||||
|
||||
if (mixmonitor_ds->fs) {
|
||||
quitting = 1;
|
||||
ast_closestream(mixmonitor_ds->fs);
|
||||
mixmonitor_ds->fs = NULL;
|
||||
ast_verb(2, "MixMonitor close filestream (mixed)\n");
|
||||
}
|
||||
|
||||
if (mixmonitor_ds->fs_read) {
|
||||
quitting = 1;
|
||||
ast_closestream(mixmonitor_ds->fs_read);
|
||||
mixmonitor_ds->fs_read = NULL;
|
||||
ast_verb(2, "MixMonitor close filestream (read)\n");
|
||||
}
|
||||
|
||||
if (mixmonitor_ds->fs_write) {
|
||||
quitting = 1;
|
||||
ast_closestream(mixmonitor_ds->fs_write);
|
||||
mixmonitor_ds->fs_write = NULL;
|
||||
ast_verb(2, "MixMonitor close filestream (write)\n");
|
||||
}
|
||||
|
||||
if (quitting) {
|
||||
mixmonitor_ds->fs_quit = 1;
|
||||
ast_verb(2, "MixMonitor close filestream\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,17 +315,51 @@ static void mixmonitor_free(struct mixmonitor *mixmonitor)
|
|||
if (mixmonitor->mixmonitor_ds) {
|
||||
ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
|
||||
ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
|
||||
ast_free(mixmonitor->filename_write);
|
||||
ast_free(mixmonitor->filename_read);
|
||||
ast_free(mixmonitor->mixmonitor_ds);
|
||||
ast_free(mixmonitor->name);
|
||||
ast_free(mixmonitor->post_process);
|
||||
}
|
||||
ast_free(mixmonitor);
|
||||
}
|
||||
}
|
||||
|
||||
static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag)
|
||||
{
|
||||
/* Initialize the file if not already done so */
|
||||
char *ext = NULL;
|
||||
char *last_slash = NULL;
|
||||
if (!ast_strlen_zero(filename)) {
|
||||
if (!*fs && !*errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
|
||||
*oflags = O_CREAT | O_WRONLY;
|
||||
*oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
|
||||
|
||||
last_slash = strrchr(filename, '/');
|
||||
|
||||
if ((ext = strrchr(filename, '.')) && (ext > last_slash)) {
|
||||
*(ext++) = '\0';
|
||||
} else {
|
||||
ext = "raw";
|
||||
}
|
||||
|
||||
if (!(*fs = ast_writefile(filename, ext, NULL, *oflags, 0, 0666))) {
|
||||
ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, ext);
|
||||
*errflag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *mixmonitor_thread(void *obj)
|
||||
{
|
||||
struct mixmonitor *mixmonitor = obj;
|
||||
|
||||
struct ast_filestream **fs = NULL;
|
||||
struct ast_filestream **fs_read = NULL;
|
||||
struct ast_filestream **fs_write = NULL;
|
||||
|
||||
unsigned int oflags;
|
||||
char *ext;
|
||||
int errflag = 0;
|
||||
struct ast_format format_slin;
|
||||
|
||||
|
@ -287,13 +367,18 @@ static void *mixmonitor_thread(void *obj)
|
|||
ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
|
||||
|
||||
fs = &mixmonitor->mixmonitor_ds->fs;
|
||||
fs_read = &mixmonitor->mixmonitor_ds->fs_read;
|
||||
fs_write = &mixmonitor->mixmonitor_ds->fs_write;
|
||||
|
||||
/* The audiohook must enter and exit the loop locked */
|
||||
ast_audiohook_lock(&mixmonitor->audiohook);
|
||||
while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
|
||||
struct ast_frame *fr = NULL;
|
||||
struct ast_frame *fr_read = NULL;
|
||||
struct ast_frame *fr_write = NULL;
|
||||
|
||||
if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin))) {
|
||||
if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, &format_slin,
|
||||
&fr_read, &fr_write))) {
|
||||
ast_audiohook_trigger_wait(&mixmonitor->audiohook);
|
||||
|
||||
if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
|
||||
|
@ -308,24 +393,28 @@ static void *mixmonitor_thread(void *obj)
|
|||
|
||||
if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->autochan->chan && ast_bridged_channel(mixmonitor->autochan->chan))) {
|
||||
ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
|
||||
/* Initialize the file if not already done so */
|
||||
if (!*fs && !errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
|
||||
oflags = O_CREAT | O_WRONLY;
|
||||
oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
|
||||
mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag);
|
||||
mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag);
|
||||
mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag);
|
||||
|
||||
if ((ext = strrchr(mixmonitor->filename, '.')))
|
||||
*(ext++) = '\0';
|
||||
else
|
||||
ext = "raw";
|
||||
/* Write out the frame(s) */
|
||||
if ((*fs_read) && (fr_read)) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
if (!(*fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0666))) {
|
||||
ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
|
||||
errflag = 1;
|
||||
for (cur = fr_read; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
ast_writestream(*fs_read, cur);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the frame(s) */
|
||||
if (*fs) {
|
||||
if ((*fs_write) && (fr_write)) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
for (cur = fr_write; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
ast_writestream(*fs_write, cur);
|
||||
}
|
||||
}
|
||||
|
||||
if ((*fs) && (fr)) {
|
||||
struct ast_frame *cur;
|
||||
|
||||
for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
|
||||
|
@ -335,7 +424,19 @@ static void *mixmonitor_thread(void *obj)
|
|||
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
|
||||
}
|
||||
/* All done! free it. */
|
||||
ast_frame_free(fr, 0);
|
||||
if (fr) {
|
||||
ast_frame_free(fr, 0);
|
||||
}
|
||||
if (fr_read) {
|
||||
ast_frame_free(fr_read, 0);
|
||||
}
|
||||
if (fr_write) {
|
||||
ast_frame_free(fr_write, 0);
|
||||
}
|
||||
|
||||
fr = NULL;
|
||||
fr_write = NULL;
|
||||
fr_read = NULL;
|
||||
|
||||
ast_audiohook_lock(&mixmonitor->audiohook);
|
||||
}
|
||||
|
@ -394,15 +495,14 @@ static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
|
||||
int readvol, int writevol, const char *post_process)
|
||||
static void launch_monitor_thread(struct ast_channel *chan, const char *filename,
|
||||
unsigned int flags, int readvol, int writevol,
|
||||
const char *post_process, const char *filename_write,
|
||||
const char *filename_read)
|
||||
{
|
||||
pthread_t thread;
|
||||
struct mixmonitor *mixmonitor;
|
||||
char postprocess2[1024] = "";
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2;
|
||||
|
||||
postprocess2[0] = 0;
|
||||
/* If a post process system command is given attach it to the structure */
|
||||
|
@ -410,18 +510,16 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
|
|||
char *p1, *p2;
|
||||
|
||||
p1 = ast_strdupa(post_process);
|
||||
for (p2 = p1; *p2 ; p2++) {
|
||||
for (p2 = p1; *p2; p2++) {
|
||||
if (*p2 == '^' && *(p2+1) == '{') {
|
||||
*p2 = '$';
|
||||
}
|
||||
}
|
||||
pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
|
||||
if (!ast_strlen_zero(postprocess2))
|
||||
len += strlen(postprocess2) + 1;
|
||||
}
|
||||
|
||||
/* Pre-allocate mixmonitor structure and spy */
|
||||
if (!(mixmonitor = ast_calloc(1, len))) {
|
||||
if (!(mixmonitor = ast_calloc(1, sizeof(*mixmonitor)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -443,15 +541,24 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
|
|||
mixmonitor_free(mixmonitor);
|
||||
return;
|
||||
}
|
||||
mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
|
||||
strcpy(mixmonitor->name, chan->name);
|
||||
|
||||
mixmonitor->name = ast_strdup(chan->name);
|
||||
|
||||
if (!ast_strlen_zero(postprocess2)) {
|
||||
mixmonitor->post_process = mixmonitor->name + strlen(mixmonitor->name) + strlen(filename) + 2;
|
||||
strcpy(mixmonitor->post_process, postprocess2);
|
||||
mixmonitor->post_process = ast_strdup(postprocess2);
|
||||
}
|
||||
|
||||
mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1;
|
||||
strcpy(mixmonitor->filename, filename);
|
||||
if (!ast_strlen_zero(filename)) {
|
||||
mixmonitor->filename = ast_strdup(filename);
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(filename_write)) {
|
||||
mixmonitor->filename_write = ast_strdup(filename_write);
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(filename_read)) {
|
||||
mixmonitor->filename_read = ast_strdup(filename_read);
|
||||
}
|
||||
|
||||
ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
|
||||
|
||||
|
@ -471,11 +578,39 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
|
|||
ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
|
||||
}
|
||||
|
||||
/* a note on filename_parse: creates directory structure and assigns absolute path from relative paths for filenames */
|
||||
/* requires immediate copying of string from return to retain data since otherwise it will immediately lose scope */
|
||||
static char *filename_parse(char *filename, char *buffer, size_t len)
|
||||
{
|
||||
char *slash;
|
||||
if (ast_strlen_zero(filename)) {
|
||||
ast_log(LOG_WARNING, "No file name was provided for a file save option.\n");
|
||||
} else if (filename[0] != '/') {
|
||||
char *build;
|
||||
build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(filename) + 3);
|
||||
sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, filename);
|
||||
filename = build;
|
||||
}
|
||||
|
||||
ast_copy_string(buffer, filename, len);
|
||||
|
||||
if ((slash = strrchr(filename, '/'))) {
|
||||
*slash = '\0';
|
||||
}
|
||||
ast_mkdir(filename, 0777);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int mixmonitor_exec(struct ast_channel *chan, const char *data)
|
||||
{
|
||||
int x, readvol = 0, writevol = 0;
|
||||
struct ast_flags flags = {0};
|
||||
char *parse, *tmp, *slash;
|
||||
char *filename_read = NULL;
|
||||
char *filename_write = NULL;
|
||||
char filename_buffer[1024] = "";
|
||||
|
||||
struct ast_flags flags = { 0 };
|
||||
char *parse;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(filename);
|
||||
AST_APP_ARG(options);
|
||||
|
@ -483,18 +618,13 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
|
|||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
|
||||
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename or ,t(filename) and/or r(filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
parse = ast_strdupa(data);
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (ast_strlen_zero(args.filename)) {
|
||||
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args.options) {
|
||||
char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
|
||||
|
@ -530,24 +660,30 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
|
|||
readvol = writevol = get_volfactor(x);
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_test_flag(&flags, MUXFLAG_WRITE)) {
|
||||
filename_write = ast_strdupa(filename_parse(opts[OPT_ARG_WRITENAME], filename_buffer, sizeof(filename_buffer)));
|
||||
}
|
||||
|
||||
if (ast_test_flag(&flags, MUXFLAG_READ)) {
|
||||
filename_read = ast_strdupa(filename_parse(opts[OPT_ARG_READNAME], filename_buffer, sizeof(filename_buffer)));
|
||||
}
|
||||
}
|
||||
|
||||
/* if not provided an absolute path, use the system-configured monitoring directory */
|
||||
if (args.filename[0] != '/') {
|
||||
char *build;
|
||||
/* If there are no file writing arguments/options for the mix monitor, send a warning message and return -1 */
|
||||
|
||||
build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(args.filename) + 3);
|
||||
sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, args.filename);
|
||||
args.filename = build;
|
||||
if (!ast_test_flag(&flags, MUXFLAG_WRITE) && !ast_test_flag(&flags, MUXFLAG_READ) && ast_strlen_zero(args.filename)) {
|
||||
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = ast_strdupa(args.filename);
|
||||
if ((slash = strrchr(tmp, '/')))
|
||||
*slash = '\0';
|
||||
ast_mkdir(tmp, 0777);
|
||||
/* If filename exists, try to create directories for it */
|
||||
if (!(ast_strlen_zero(args.filename))) {
|
||||
args.filename = ast_strdupa(filename_parse(args.filename, filename_buffer, sizeof(filename_buffer)));
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
|
||||
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
|
||||
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process, filename_write, filename_read);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3336,6 +3336,7 @@ static int retrieve_file(char *dir, int msgnum)
|
|||
fprintf(f, "[message]\n");
|
||||
for (x = 0; x < colcount; x++) {
|
||||
rowdata[0] = '\0';
|
||||
colsize = 0;
|
||||
collen = sizeof(coltitle);
|
||||
res = SQLDescribeCol(stmt, x + 1, (unsigned char *) coltitle, sizeof(coltitle), &collen,
|
||||
&datatype, &colsize, &decimaldigits, &nullable);
|
||||
|
|
|
@ -2109,6 +2109,60 @@ static void my_deadlock_avoidance_private(void *pvt)
|
|||
DEADLOCK_AVOIDANCE(&p->lock);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Post an AMI DAHDI channel association event.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param p DAHDI private pointer
|
||||
* \param chan Channel associated with the private pointer
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
|
||||
{
|
||||
char ch_name[20];
|
||||
|
||||
if (p->channel < CHAN_PSEUDO) {
|
||||
/* No B channel */
|
||||
snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
|
||||
} else if (p->channel == CHAN_PSEUDO) {
|
||||
/* Pseudo channel */
|
||||
strcpy(ch_name, "pseudo");
|
||||
} else {
|
||||
/* Real channel */
|
||||
snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
|
||||
}
|
||||
ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
|
||||
"Channel: %s\r\n"
|
||||
"Uniqueid: %s\r\n"
|
||||
"DAHDISpan: %d\r\n"
|
||||
"DAHDIChannel: %s\r\n",
|
||||
chan->name,
|
||||
chan->uniqueid,
|
||||
p->span,
|
||||
ch_name);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PRI
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Post an AMI DAHDI channel association event.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pvt DAHDI private pointer
|
||||
* \param chan Channel associated with the private pointer
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
|
||||
{
|
||||
struct dahdi_pvt *p = pvt;
|
||||
|
||||
dahdi_ami_channel_event(p, chan);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on
|
||||
* returns the last value of the linear setting
|
||||
*/
|
||||
|
@ -3294,6 +3348,7 @@ static struct sig_pri_callback dahdi_pri_callbacks =
|
|||
.module_ref = my_module_ref,
|
||||
.module_unref = my_module_unref,
|
||||
.open_media = my_pri_open_media,
|
||||
.ami_channel_event = my_ami_channel_event,
|
||||
};
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
|
||||
|
@ -5341,7 +5396,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
|
|||
|
||||
c = args.ext;
|
||||
if (!p->hidecallerid) {
|
||||
l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
|
||||
l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
|
||||
} else {
|
||||
l = NULL;
|
||||
}
|
||||
|
@ -6792,6 +6847,41 @@ static int dahdi_func_read(struct ast_channel *chan, const char *function, char
|
|||
ast_mutex_lock(&p->lock);
|
||||
snprintf(buf, len, "%f", p->txgain);
|
||||
ast_mutex_unlock(&p->lock);
|
||||
} else if (!strcasecmp(data, "dahdi_channel")) {
|
||||
ast_mutex_lock(&p->lock);
|
||||
snprintf(buf, len, "%d", p->channel);
|
||||
ast_mutex_unlock(&p->lock);
|
||||
} else if (!strcasecmp(data, "dahdi_span")) {
|
||||
ast_mutex_lock(&p->lock);
|
||||
snprintf(buf, len, "%d", p->span);
|
||||
ast_mutex_unlock(&p->lock);
|
||||
} else if (!strcasecmp(data, "dahdi_type")) {
|
||||
ast_mutex_lock(&p->lock);
|
||||
switch (p->sig) {
|
||||
#if defined(HAVE_OPENR2)
|
||||
case SIG_MFCR2:
|
||||
ast_copy_string(buf, "mfc/r2", len);
|
||||
break;
|
||||
#endif /* defined(HAVE_OPENR2) */
|
||||
#if defined(HAVE_PRI)
|
||||
case SIG_PRI_LIB_HANDLE_CASES:
|
||||
ast_copy_string(buf, "pri", len);
|
||||
break;
|
||||
#endif /* defined(HAVE_PRI) */
|
||||
case 0:
|
||||
ast_copy_string(buf, "pseudo", len);
|
||||
break;
|
||||
#if defined(HAVE_SS7)
|
||||
case SIG_SS7:
|
||||
ast_copy_string(buf, "ss7", len);
|
||||
break;
|
||||
#endif /* defined(HAVE_SS7) */
|
||||
default:
|
||||
/* The only thing left is analog ports. */
|
||||
ast_copy_string(buf, "analog", len);
|
||||
break;
|
||||
}
|
||||
ast_mutex_unlock(&p->lock);
|
||||
#if defined(HAVE_PRI)
|
||||
#if defined(HAVE_PRI_REVERSE_CHARGE)
|
||||
} else if (!strcasecmp(data, "reversecharge")) {
|
||||
|
@ -9530,6 +9620,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
|
|||
|
||||
ast_module_ref(ast_module_info->self);
|
||||
|
||||
dahdi_ami_channel_event(i, tmp);
|
||||
if (startpbx) {
|
||||
#ifdef HAVE_OPENR2
|
||||
if (i->mfcr2call) {
|
||||
|
@ -13089,6 +13180,7 @@ static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
|
|||
nobch_channel = CHAN_PSEUDO - 1;
|
||||
}
|
||||
pvt->channel = nobch_channel;
|
||||
pvt->span = pri->span;
|
||||
chan->channel = pvt->channel;
|
||||
|
||||
dahdi_nobch_insert(pri, pvt);
|
||||
|
|
|
@ -280,16 +280,16 @@ static int unload_module(void)
|
|||
static int load_module(void)
|
||||
{
|
||||
ast_format_set(&prefformat, AST_FORMAT_SLINEAR, 0);
|
||||
if (!(nbs_tech.capabilities == ast_format_cap_alloc())) {
|
||||
return -1;
|
||||
if (!(nbs_tech.capabilities = ast_format_cap_alloc())) {
|
||||
return AST_MODULE_LOAD_FAILURE;
|
||||
}
|
||||
ast_format_cap_add(nbs_tech.capabilities, &prefformat);
|
||||
/* Make sure we can register our channel type */
|
||||
if (ast_channel_register(&nbs_tech)) {
|
||||
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
|
||||
return -1;
|
||||
return AST_MODULE_LOAD_DECLINE;
|
||||
}
|
||||
return 0;
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Network Broadcast Sound Support");
|
||||
|
|
|
@ -23178,7 +23178,7 @@ static int sip_pidf_validate(struct sip_request *req, struct ast_xml_doc **pidf_
|
|||
static int cc_esc_publish_handler(struct sip_pvt *pvt, struct sip_request *req, struct event_state_compositor *esc, struct sip_esc_entry *esc_entry)
|
||||
{
|
||||
const char *uri = REQ_OFFSET_TO_STR(req, rlPart2);
|
||||
struct ast_cc_agent *agent = find_sip_cc_agent_by_notify_uri(uri);
|
||||
struct ast_cc_agent *agent;
|
||||
struct sip_cc_agent_pvt *agent_pvt;
|
||||
struct ast_xml_doc *pidf_doc = NULL;
|
||||
const char *basic_status = NULL;
|
||||
|
@ -23191,7 +23191,7 @@ static int cc_esc_publish_handler(struct sip_pvt *pvt, struct sip_request *req,
|
|||
struct ast_xml_node *basic_node;
|
||||
int res = 0;
|
||||
|
||||
if (!agent) {
|
||||
if (!((agent = find_sip_cc_agent_by_notify_uri(uri)) || (agent = find_sip_cc_agent_by_subscribe_uri(uri)))) {
|
||||
ast_log(LOG_WARNING, "Could not find agent using uri '%s'\n", uri);
|
||||
transmit_response(pvt, "412 Conditional Request Failed", req);
|
||||
return -1;
|
||||
|
@ -23768,7 +23768,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
|
|||
if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) {
|
||||
transmit_response(p, "404 Not found (no mailbox)", req);
|
||||
pvt_set_needdestroy(p, "received 404 response");
|
||||
ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name);
|
||||
ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", S_OR(authpeer->name, ""));
|
||||
if (authpeer)
|
||||
unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 4)");
|
||||
return 0;
|
||||
|
@ -26154,7 +26154,6 @@ static void add_peer_mailboxes(struct sip_peer *peer, const char *value)
|
|||
AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) {
|
||||
if (!strcmp(mailbox->mailbox, mbox) && !strcmp(S_OR(mailbox->context, ""), S_OR(context, ""))) {
|
||||
duplicate = 1;
|
||||
mailbox->delme = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,7 +197,7 @@ static void sig_pri_make_cc_dialstring(struct sig_pri_chan *p, char *buf, size_t
|
|||
* \brief Reevaluate the PRI span device state.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri Asterisk D channel control structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \return Nothing
|
||||
*
|
||||
|
@ -932,6 +932,24 @@ static void sig_pri_open_media(struct sig_pri_chan *p)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Post an AMI B channel association event.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param p Channel private control structure.
|
||||
*
|
||||
* \note Assumes the private and owner are locked.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
static void sig_pri_ami_channel_event(struct sig_pri_chan *p)
|
||||
{
|
||||
if (p->calls->ami_channel_event) {
|
||||
p->calls->ami_channel_event(p->chan_pvt, p->owner);
|
||||
}
|
||||
}
|
||||
|
||||
struct ast_channel *sig_pri_request(struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_channel *requestor, int transfercapability)
|
||||
{
|
||||
struct ast_channel *ast;
|
||||
|
@ -1024,7 +1042,7 @@ static int pri_find_dchan(struct sig_pri_span *pri)
|
|||
* \brief Obtain the sig_pri owner channel lock if the owner exists.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -1055,7 +1073,7 @@ static void sig_pri_lock_owner(struct sig_pri_span *pri, int chanpos)
|
|||
* \brief Queue the given frame onto the owner channel.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
* \param frame Frame to queue onto the owner channel.
|
||||
*
|
||||
|
@ -1078,7 +1096,7 @@ static void pri_queue_frame(struct sig_pri_span *pri, int chanpos, struct ast_fr
|
|||
* \brief Queue a control frame of the specified subclass onto the owner channel.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
* \param subclass Control frame subclass to queue onto the owner channel.
|
||||
*
|
||||
|
@ -1105,7 +1123,7 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas
|
|||
* \brief Find the channel associated with the libpri call.
|
||||
* \since 1.10
|
||||
*
|
||||
* \param pri sig_pri span controller to find interface.
|
||||
* \param pri PRI span control structure.
|
||||
* \param call LibPRI opaque call pointer to find.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -1134,7 +1152,7 @@ static int pri_find_principle_by_call(struct sig_pri_span *pri, q931_call *call)
|
|||
* \internal
|
||||
* \brief Find the private structure for the libpri call.
|
||||
*
|
||||
* \param pri Span controller structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param channel LibPRI encoded channel ID.
|
||||
* \param call LibPRI opaque call pointer.
|
||||
*
|
||||
|
@ -1190,7 +1208,7 @@ static int pri_find_principle(struct sig_pri_span *pri, int channel, q931_call *
|
|||
* \internal
|
||||
* \brief Fixup the private structure associated with the libpri call.
|
||||
*
|
||||
* \param pri Span controller structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param principle Array-index into private array to move call to if not already there.
|
||||
* \param call LibPRI opaque call pointer to find if need to move call.
|
||||
*
|
||||
|
@ -1333,6 +1351,10 @@ static int pri_fixup_principle(struct sig_pri_span *pri, int principle, q931_cal
|
|||
sig_pri_open_media(new_chan);
|
||||
}
|
||||
|
||||
if (new_chan->owner) {
|
||||
sig_pri_ami_channel_event(new_chan);
|
||||
}
|
||||
|
||||
sig_pri_unlock_private(old_chan);
|
||||
if (new_chan->owner) {
|
||||
ast_channel_unlock(new_chan->owner);
|
||||
|
@ -1435,7 +1457,7 @@ tryanotherpos:
|
|||
* \since 1.8
|
||||
*
|
||||
* \param pvt Channel to init the configuration.
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
*
|
||||
|
@ -1494,7 +1516,7 @@ static int pri_find_empty_chan(struct sig_pri_span *pri, int backwards)
|
|||
* \brief Find or create an empty no-B-channel interface to use.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri span controller to find interface.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
*
|
||||
|
@ -1741,7 +1763,7 @@ static void sig_pri_party_name_convert(struct ast_party_name *ast_name, const st
|
|||
*
|
||||
* \param ast_number Asterisk party number structure to fill. Must already be set initialized.
|
||||
* \param pri_number libpri party number structure containing source information.
|
||||
* \param pri Span controlling structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \note The filled in ast_number structure needs to be destroyed by
|
||||
* ast_party_number_free() when it is no longer needed.
|
||||
|
@ -1766,7 +1788,7 @@ static void sig_pri_party_number_convert(struct ast_party_number *ast_number, co
|
|||
*
|
||||
* \param ast_id Asterisk party id structure to fill. Must already be set initialized.
|
||||
* \param pri_id libpri party id structure containing source information.
|
||||
* \param pri Span controlling structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \note The filled in ast_id structure needs to be destroyed by
|
||||
* ast_party_id_free() when it is no longer needed.
|
||||
|
@ -1796,7 +1818,7 @@ static void sig_pri_party_id_convert(struct ast_party_id *ast_id, const struct p
|
|||
* \param ast_redirecting Asterisk redirecting structure to fill.
|
||||
* \param pri_redirecting libpri redirecting structure containing source information.
|
||||
* \param ast_guide Asterisk redirecting structure to use as an initialization guide.
|
||||
* \param pri Span controlling structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \note The filled in ast_redirecting structure needs to be destroyed by
|
||||
* ast_party_redirecting_free() when it is no longer needed.
|
||||
|
@ -1918,7 +1940,7 @@ static void sig_pri_event_party_id(struct ast_str **msg, const char *prefix, str
|
|||
* \brief Handle the MCID event.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param mcid MCID event parameters.
|
||||
* \param owner Asterisk channel associated with the call.
|
||||
* NULL if Asterisk no longer has the ast_channel struct.
|
||||
|
@ -2022,7 +2044,7 @@ typedef void (*xfer_rsp_callback)(void *data, int is_successful);
|
|||
* \brief Attempt to transfer the two calls to each other.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param call_1_pri First call involved in the transfer. (transferee; usually on hold)
|
||||
* \param call_1_held TRUE if call_1_pri is on hold.
|
||||
* \param call_2_pri Second call involved in the transfer. (target; usually active/ringing)
|
||||
|
@ -2208,7 +2230,7 @@ static int sig_pri_cc_agent_cmp_cc_id(void *obj, void *arg, int flags)
|
|||
* \brief Find the CC agent by libpri cc_id.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param cc_id CC record ID to find.
|
||||
*
|
||||
* \note
|
||||
|
@ -2259,7 +2281,7 @@ static int sig_pri_cc_monitor_cmp_cc_id(void *obj, void *arg, int flags)
|
|||
* \brief Find the CC monitor instance by libpri cc_id.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param cc_id CC record ID to find.
|
||||
*
|
||||
* \note
|
||||
|
@ -2311,7 +2333,7 @@ static void sig_pri_cc_monitor_instance_destroy(void *data)
|
|||
* \since 1.8
|
||||
*
|
||||
* \param core_id CC core ID.
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param cc_id CC record ID.
|
||||
* \param device_name Name of device (Asterisk channel name less sequence number).
|
||||
*
|
||||
|
@ -2355,7 +2377,7 @@ static struct sig_pri_cc_monitor_instance *sig_pri_cc_monitor_instance_init(int
|
|||
* \brief Announce to the CC core that protocol CC monitor is available for this call.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
* \param cc_id CC record ID.
|
||||
* \param service CCBS/CCNR indication.
|
||||
|
@ -2431,7 +2453,7 @@ static int sig_pri_cc_available(struct sig_pri_span *pri, int chanpos, long cc_i
|
|||
* \brief Check if generic CC monitor is needed and request it.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
* \param service CCBS/CCNR indication.
|
||||
*
|
||||
|
@ -2531,7 +2553,7 @@ done:
|
|||
* \brief The CC link canceled the CC instance.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param cc_id CC record ID.
|
||||
* \param is_agent TRUE if the cc_id is for an agent.
|
||||
*
|
||||
|
@ -3453,7 +3475,7 @@ static void sig_pri_aoc_e_from_ast(struct sig_pri_chan *pvt, struct ast_aoc_deco
|
|||
* \brief send an AOC-E termination request on ast_channel and set
|
||||
* hangup delay.
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
* \param ms to delay hangup
|
||||
*
|
||||
|
@ -3527,7 +3549,7 @@ static int sig_pri_is_cis_call(int channel)
|
|||
* \brief Handle the CIS associated PRI subcommand events.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param event_id PRI event id
|
||||
* \param subcmds Subcommands to process if any. (Could be NULL).
|
||||
* \param call_rsp libpri opaque call structure to send any responses toward.
|
||||
|
@ -3780,7 +3802,7 @@ static int detect_aoc_e_subcmd(const struct pri_subcommands *subcmds)
|
|||
* \brief Handle the call associated PRI subcommand events.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param chanpos Channel position in the span.
|
||||
* \param event_id PRI event id
|
||||
* \param channel PRI encoded span/channel
|
||||
|
@ -3905,16 +3927,35 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev
|
|||
struct pri_party_redirecting pri_deflection;
|
||||
|
||||
if (!call_rsp) {
|
||||
ast_channel_unlock(owner);
|
||||
ast_log(LOG_WARNING,
|
||||
"CallRerouting/CallDeflection to '%s' without call!\n",
|
||||
subcmd->u.rerouting.deflection.to.number.str);
|
||||
"Span %d: %s tried CallRerouting/CallDeflection to '%s' without call!\n",
|
||||
pri->span, owner->name, subcmd->u.rerouting.deflection.to.number.str);
|
||||
ast_channel_unlock(owner);
|
||||
break;
|
||||
}
|
||||
if (ast_strlen_zero(subcmd->u.rerouting.deflection.to.number.str)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Span %d: %s tried CallRerouting/CallDeflection to empty number!\n",
|
||||
pri->span, owner->name);
|
||||
pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
|
||||
PRI_REROUTING_RSP_INVALID_NUMBER);
|
||||
ast_channel_unlock(owner);
|
||||
break;
|
||||
}
|
||||
|
||||
pri_deflection = subcmd->u.rerouting.deflection;
|
||||
ast_verb(3, "Span %d: %s is CallRerouting/CallDeflection to '%s'.\n",
|
||||
pri->span, owner->name, subcmd->u.rerouting.deflection.to.number.str);
|
||||
|
||||
ast_string_field_set(owner, call_forward, pri_deflection.to.number.str);
|
||||
/*
|
||||
* Send back positive ACK to CallRerouting/CallDeflection.
|
||||
*
|
||||
* Note: This call will be hungup by the core when it processes
|
||||
* the call_forward string.
|
||||
*/
|
||||
pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
|
||||
PRI_REROUTING_RSP_OK_CLEAR);
|
||||
|
||||
pri_deflection = subcmd->u.rerouting.deflection;
|
||||
|
||||
/* Adjust the deflecting to number based upon the subscription option. */
|
||||
switch (subcmd->u.rerouting.subscription_option) {
|
||||
|
@ -3940,17 +3981,12 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev
|
|||
ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
|
||||
ast_party_redirecting_free(&ast_redirecting);
|
||||
|
||||
/*
|
||||
* Send back positive ACK to CallRerouting/CallDeflection.
|
||||
*
|
||||
* Note: This call will be hungup by the dial application when
|
||||
* it processes the call_forward string set above.
|
||||
*/
|
||||
pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
|
||||
PRI_REROUTING_RSP_OK_CLEAR);
|
||||
/* Request the core to forward to the new number. */
|
||||
ast_string_field_set(owner, call_forward,
|
||||
subcmd->u.rerouting.deflection.to.number.str);
|
||||
|
||||
/* This line is BUSY to further attempts by this dialing attempt. */
|
||||
ast_queue_control(owner, AST_CONTROL_BUSY);
|
||||
/* Wake up the channel. */
|
||||
ast_queue_frame(owner, &ast_null_frame);
|
||||
|
||||
ast_channel_unlock(owner);
|
||||
}
|
||||
|
@ -4153,7 +4189,7 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev
|
|||
* \brief Kill the call.
|
||||
* \since 1.10
|
||||
*
|
||||
* \param pri Span controller to find interface.
|
||||
* \param pri PRI span control structure.
|
||||
* \param call LibPRI opaque call pointer to find.
|
||||
* \param cause Reason call was killed.
|
||||
*
|
||||
|
@ -4847,7 +4883,7 @@ static void sig_pri_ami_hold_event(struct ast_channel *chan, int is_held)
|
|||
* \brief Handle the hold event from libpri.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param ev Hold event received.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -4923,7 +4959,7 @@ done_with_private:;
|
|||
* \brief Handle the hold acknowledge event from libpri.
|
||||
* \since 1.10
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param ev Hold acknowledge event received.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -4969,7 +5005,7 @@ static void sig_pri_handle_hold_ack(struct sig_pri_span *pri, pri_event *ev)
|
|||
* \brief Handle the hold reject event from libpri.
|
||||
* \since 1.10
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param ev Hold reject event received.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -5011,7 +5047,7 @@ static void sig_pri_handle_hold_rej(struct sig_pri_span *pri, pri_event *ev)
|
|||
* \brief Handle the retrieve event from libpri.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param ev Retrieve event received.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -5080,7 +5116,7 @@ static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev)
|
|||
* \brief Handle the retrieve acknowledge event from libpri.
|
||||
* \since 1.10
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param ev Retrieve acknowledge event received.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -5119,7 +5155,7 @@ static void sig_pri_handle_retrieve_ack(struct sig_pri_span *pri, pri_event *ev)
|
|||
* \brief Handle the retrieve reject event from libpri.
|
||||
* \since 1.10
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param ev Retrieve reject event received.
|
||||
*
|
||||
* \note Assumes the pri->lock is already obtained.
|
||||
|
@ -7792,7 +7828,7 @@ static int sig_pri_available_check(struct sig_pri_chan *pvt)
|
|||
* \brief Get an available call waiting interface.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri sig_pri PRI control structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \retval cw Call waiting interface to use.
|
||||
* \retval NULL if no call waiting interface available.
|
||||
|
@ -7917,7 +7953,7 @@ int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char
|
|||
* \brief Send a MWI indication to the given span.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri Asterisk D channel control structure.
|
||||
* \param pri PRI span control structure.
|
||||
* \param mbox_number Mailbox number
|
||||
* \param mbox_context Mailbox context
|
||||
* \param num_messages Number of messages waiting.
|
||||
|
@ -7980,7 +8016,7 @@ static void sig_pri_mwi_event_cb(const struct ast_event *event, void *userdata)
|
|||
* \brief Send update MWI indications from the event cache.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri Asterisk D channel control structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
|
@ -8016,7 +8052,7 @@ static void sig_pri_mwi_cache_update(struct sig_pri_span *pri)
|
|||
* \brief Stop PRI span.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri Asterisk D channel control structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
|
@ -8072,7 +8108,7 @@ static int sig_pri_cmp_pri_chans(const void *left, const void *right)
|
|||
* \brief Sort the PRI B channel private pointer array.
|
||||
* \since 1.8
|
||||
*
|
||||
* \param pri PRI Span controlling structure.
|
||||
* \param pri PRI span control structure.
|
||||
*
|
||||
* \details
|
||||
* Since the chan_dahdi.conf file can declare channels in any order, we need to sort
|
||||
|
|
|
@ -200,6 +200,16 @@ struct sig_pri_callback {
|
|||
|
||||
void (* const open_media)(void *pvt);
|
||||
|
||||
/*!
|
||||
* \brief Post an AMI B channel association event.
|
||||
*
|
||||
* \param pvt Private structure of the user of this module.
|
||||
* \param chan Channel associated with the private pointer
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void (* const ami_channel_event)(void *pvt, struct ast_channel *chan);
|
||||
|
||||
/*! Reference the parent module. */
|
||||
void (*module_ref)(void);
|
||||
/*! Unreference the parent module. */
|
||||
|
|
|
@ -47,6 +47,13 @@ int sip_acf_channel_read(struct ast_channel *chan, const char *funcname, char *p
|
|||
AST_APP_ARG(type);
|
||||
AST_APP_ARG(field);
|
||||
);
|
||||
|
||||
/* Check for zero arguments */
|
||||
if (ast_strlen_zero(parse)) {
|
||||
ast_log(LOG_ERROR, "Cannot call %s without arguments\n", funcname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
/* Sanity check */
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
* \ingroup codecs
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>resample</depend>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
#include "speex/speex_resampler.h"
|
||||
|
||||
|
|
|
@ -45,28 +45,33 @@ ifeq ($(shell $(CC) -v 2>&1 | awk '/^gcc version/ { split($$3, v, "."); printf "
|
|||
OPTIMIZE=-O2
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring $(shell uname -s),Darwin SunOS))
|
||||
ifeq (,$(strip $(findstring $(PROC) ,"x86_64 amd64 ultrasparc sparc64 arm armv5b armeb ppc powerpc ppc64 ia64 s390 bfin mipsel mips ")))
|
||||
ifeq (,$(strip $(findstring $(shell uname -m) ,"ppc ppc64 alpha armv4l s390 ")))
|
||||
OPTIMIZE+=-march=$(PROC)
|
||||
# If the compiler's '-march' flag has been specified already, then assume it's a value
|
||||
# that is what the user wants (or has been determined by the configure script). If not,
|
||||
# do some simple logic to set a decent value
|
||||
ifeq ($(findstring -march,$(_ASTCFLAGS) $(ASTCFLAGS)),)
|
||||
ifeq (,$(findstring $(shell uname -s),Darwin SunOS))
|
||||
ifeq (,$(strip $(findstring $(PROC) ,"x86_64 amd64 ultrasparc sparc64 arm armv5b armeb ppc powerpc ppc64 ia64 s390 bfin mipsel mips ")))
|
||||
ifeq (,$(strip $(findstring $(shell uname -m) ,"ppc ppc64 alpha armv4l s390 ")))
|
||||
OPTIMIZE+=-march=$(PROC)
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifneq (,$(findstring $(OSARCH),Darwin))
|
||||
ifeq ($(shell /usr/bin/sw_vers -productVersion | cut -c1-4),10.6)
|
||||
# Snow Leopard reports i386, even though it's really x86_64
|
||||
OPTIMIZE+=-mtune=native
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else
|
||||
ifneq (,$(findstring $(OSARCH),Darwin))
|
||||
ifeq ($(shell /usr/bin/sw_vers -productVersion | cut -c1-4),10.6)
|
||||
# Snow Leopard reports i386, even though it's really x86_64
|
||||
OPTIMIZE+=-mtune=native
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
|
||||
#This works for even old (2.96) versions of gcc and provides a small boost either way.
|
||||
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it.
|
||||
#So we go lowest common available by gcc and go a step down, still a step up from
|
||||
#the default as we now have a better instruction set to work with. - Belgarath
|
||||
ifeq ($(PROC),ultrasparc)
|
||||
OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3
|
||||
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
|
||||
#This works for even old (2.96) versions of gcc and provides a small boost either way.
|
||||
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it.
|
||||
#So we go lowest common available by gcc and go a step down, still a step up from
|
||||
#the default as we now have a better instruction set to work with. - Belgarath
|
||||
ifeq ($(PROC),ultrasparc)
|
||||
OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3
|
||||
endif
|
||||
endif
|
||||
|
||||
PG =
|
||||
|
|
|
@ -27,30 +27,35 @@ CFLAGS+= -fPIC -Wno-comment
|
|||
# fails miserably. Remove it for the time being.
|
||||
_ASTCFLAGS:=$(_ASTCFLAGS:-Werror=)
|
||||
|
||||
#fix for PPC processors and ALPHA, And UltraSparc too
|
||||
ifneq ($(OSARCH),Darwin)
|
||||
ifneq ($(findstring BSD,${OSARCH}),BSD)
|
||||
ifneq ($(PROC),ppc)
|
||||
ifneq ($(PROC),x86_64)
|
||||
ifneq ($(PROC),alpha)
|
||||
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
|
||||
#This works for even old (2.96) versions of gcc and provides a small boost either way.
|
||||
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn.t support it.
|
||||
#So we go lowest common available by gcc and go a step down, still a step up from
|
||||
#the default as we now have a better instruction set to work with. - Belgarath
|
||||
ifeq ($(PROC),ultrasparc)
|
||||
CFLAGS+= -mtune=$(PROC) -mcpu=v8 -O3 -fomit-frame-pointer
|
||||
else
|
||||
ifneq ($(OSARCH),SunOS)
|
||||
ifneq ($(OSARCH),arm)
|
||||
# CFLAGS+= -march=$(PROC)
|
||||
# If the compiler's '-march' flag has been specified already, then assume it's a value
|
||||
# that is what the user wants (or has been determined by the configure script). If not,
|
||||
# do some simple logic to set a decent value
|
||||
ifeq ($(findstring -march,$(_ASTCFLAGS) $(ASTCFLAGS)),)
|
||||
#fix for PPC processors and ALPHA, And UltraSparc too
|
||||
ifneq ($(OSARCH),Darwin)
|
||||
ifneq ($(findstring BSD,${OSARCH}),BSD)
|
||||
ifneq ($(PROC),ppc)
|
||||
ifneq ($(PROC),x86_64)
|
||||
ifneq ($(PROC),alpha)
|
||||
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
|
||||
#This works for even old (2.96) versions of gcc and provides a small boost either way.
|
||||
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn.t support it.
|
||||
#So we go lowest common available by gcc and go a step down, still a step up from
|
||||
#the default as we now have a better instruction set to work with. - Belgarath
|
||||
ifeq ($(PROC),ultrasparc)
|
||||
CFLAGS+= -mtune=$(PROC) -mcpu=v8 -O3 -fomit-frame-pointer
|
||||
else
|
||||
ifneq ($(OSARCH),SunOS)
|
||||
ifneq ($(OSARCH),arm)
|
||||
# CFLAGS+= -march=$(PROC)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
LIB = $(LIB_TARGET_DIR)/liblpc10.a
|
||||
|
|
|
@ -32,6 +32,13 @@
|
|||
;appdata = tt-weasels ; Data part of application to execute on answer
|
||||
;
|
||||
;waittime = 30 ; How long to wait for an answer, defaults to 30 seconds
|
||||
;
|
||||
; Channel variables can be set on the notification channel. The format is
|
||||
; setvar=name=value. Variable subsitution is done on the value to allow the use of dialplan
|
||||
; functions like CALENDAR_EVENT. The variables are set in order, so one can use the value
|
||||
; of earlier variables in the definition of later ones.
|
||||
;
|
||||
;setvar = CALLERID(name)=${CALENDAR_EVENT(summary)}
|
||||
|
||||
;[calendar2]
|
||||
; Note: Support for Exchange Server 2003
|
||||
|
|
|
@ -197,3 +197,14 @@ extensions = {
|
|||
};
|
||||
}
|
||||
|
||||
hints = {
|
||||
demo = {
|
||||
[1000] = "SIP/1000";
|
||||
[1001] = "SIP/1001";
|
||||
};
|
||||
|
||||
default = {
|
||||
["1234"] = "SIP/1234";
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ ring = 425/1000,0/3000
|
|||
congestion = 425/167,0/167
|
||||
callwaiting = 1400/175,0/175,1400/175,0/3500
|
||||
; DIALRECALL - not specified
|
||||
dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440"
|
||||
dialrecall = !350+440/100,!0/100,!350+440/100,!0/100,!350+440/100,!0/100,350+440
|
||||
; RECORDTONE - not specified
|
||||
record = 1400/500,0/15000
|
||||
info = 900/330,1400/330,1800/330,0/1000
|
||||
|
|
|
@ -179,8 +179,8 @@ udpbindaddr=0.0.0.0 ; IP address to bind UDP listen socket to (0.0.0
|
|||
;
|
||||
; Note also that while Asterisk currently will parse an Allow header to learn
|
||||
; what methods an endpoint supports, the only actual use for this currently
|
||||
; is for determining if Asterisk may send connected line UPDATE requests. Its
|
||||
; use may be expanded in the future.
|
||||
; is for determining if Asterisk may send connected line UPDATE requests and
|
||||
; MESSAGE requests. Its use may be expanded in the future.
|
||||
;
|
||||
; disallowed_methods = UPDATE
|
||||
|
||||
|
|
51
configure.ac
51
configure.ac
|
@ -301,47 +301,6 @@ __EOL__
|
|||
rm -rf ${tmp}
|
||||
fi
|
||||
])
|
||||
AC_CACHE_CHECK([for flex that ignores fwrite return value], [ac_cv_FLEX_WORKAROUND], [
|
||||
if test "x$FLEX" != "x:" ; then
|
||||
# Create a temporary directory $tmp in $TMPDIR (default /tmp).
|
||||
# Use mktemp if possible; otherwise fall back on mkdir,
|
||||
# with $RANDOM to make collisions less likely.
|
||||
: ${TMPDIR=/tmp}
|
||||
{
|
||||
tmp=`
|
||||
(umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null
|
||||
` &&
|
||||
test -n "$tmp" && test -d "$tmp"
|
||||
} || {
|
||||
tmp=$TMPDIR/foo$$-$RANDOM
|
||||
(umask 077 && mkdir "$tmp")
|
||||
} || exit $?
|
||||
cat >$tmp/test.fl <<__EOL__
|
||||
%{
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
static void yyunput (int c,char *buf_ptr ) __attribute__((unused));
|
||||
static int input(void) __attribute__((unused));
|
||||
%}
|
||||
|
||||
%%
|
||||
username printf( "%s", getlogin() );
|
||||
__EOL__
|
||||
${FLEX} -o ${tmp}/test.c ${tmp}/test.fl
|
||||
${CC} -o ${tmp}/test.o -c ${tmp}/test.c -Wall -Werror >/dev/null 2>&1
|
||||
if test -e "${tmp}/test.o"; then
|
||||
ac_cv_FLEX_WORKAROUND=no
|
||||
else
|
||||
ac_cv_FLEX_WORKAROUND=yes
|
||||
fi
|
||||
rm -rf ${tmp}
|
||||
fi
|
||||
])
|
||||
|
||||
if test "x${ac_cv_FLEX_WORKAROUND}" = "xyes"; then
|
||||
AC_DEFINE([NEED_FLEX_FWRITE_WORKAROUND], 1, [Define to 1 if your system has a version of flex that does not check the return value of fwrite.])
|
||||
fi
|
||||
|
||||
if test "x${ac_cv_path_BISON2}" = "x" ; then
|
||||
BISON=:
|
||||
PBX_BISON=0
|
||||
|
@ -960,6 +919,16 @@ else
|
|||
fi
|
||||
AC_SUBST(AST_SHADOW_WARNINGS)
|
||||
|
||||
AC_MSG_CHECKING(for -march=native)
|
||||
if $(${CC} -march=native -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
|
||||
AC_MSG_RESULT(yes)
|
||||
AST_MARCH_NATIVE="-march=native"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AST_MARCH_NATIVE=
|
||||
fi
|
||||
AC_SUBST(AST_MARCH_NATIVE)
|
||||
|
||||
AC_MSG_CHECKING(for sysinfo)
|
||||
AC_LINK_IFELSE(
|
||||
AC_LANG_PROGRAM([#include <sys/sysinfo.h>],
|
||||
|
|
|
@ -224,6 +224,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
</enumlist>
|
||||
<para><emphasis>chan_dahdi</emphasis> provides the following additional options:</para>
|
||||
<enumlist>
|
||||
<enum name="dahdi_channel">
|
||||
<para>R/O DAHDI channel related to this channel.</para>
|
||||
</enum>
|
||||
<enum name="dahdi_span">
|
||||
<para>R/O DAHDI span related to this channel.</para>
|
||||
</enum>
|
||||
<enum name="dahdi_type">
|
||||
<para>R/O DAHDI channel type, one of:</para>
|
||||
<enumlist>
|
||||
<enum name="analog" />
|
||||
<enum name="mfc/r2" />
|
||||
<enum name="pri" />
|
||||
<enum name="pseudo" />
|
||||
<enum name="ss7" />
|
||||
</enumlist>
|
||||
</enum>
|
||||
<enum name="keypad_digits">
|
||||
<para>R/O PRI Keypad digits that came in with the SETUP message.</para>
|
||||
</enum>
|
||||
|
|
|
@ -304,29 +304,30 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
|
|||
pbx_builtin_setvar_helper(chan, varname, NULL);
|
||||
}
|
||||
pbx_builtin_setvar_helper(chan, "VALUE", NULL);
|
||||
}
|
||||
|
||||
/*!\note
|
||||
* Okay, this part is confusing. Transactions belong to a single database
|
||||
* handle. Therefore, when working with transactions, we CANNOT failover
|
||||
* to multiple DSNs. We MUST have a single handle all the way through the
|
||||
* transaction, or else we CANNOT enforce atomicity.
|
||||
*/
|
||||
for (dsn = 0; dsn < 5; dsn++) {
|
||||
/*!\note
|
||||
* Okay, this part is confusing. Transactions belong to a single database
|
||||
* handle. Therefore, when working with transactions, we CANNOT failover
|
||||
* to multiple DSNs. We MUST have a single handle all the way through the
|
||||
* transaction, or else we CANNOT enforce atomicity.
|
||||
*/
|
||||
for (dsn = 0; dsn < 5; dsn++) {
|
||||
if (!ast_strlen_zero(query->writehandle[dsn])) {
|
||||
if (transactional) {
|
||||
/* This can only happen second time through or greater. */
|
||||
ast_log(LOG_WARNING, "Transactions do not work well with multiple DSNs for 'writehandle'\n");
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(query->writehandle[dsn])) {
|
||||
if ((obj = ast_odbc_retrieve_transaction_obj(chan, query->writehandle[dsn]))) {
|
||||
transactional = 1;
|
||||
} else {
|
||||
obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
|
||||
transactional = 0;
|
||||
}
|
||||
if (obj && (stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(buf)))) {
|
||||
break;
|
||||
}
|
||||
if ((obj = ast_odbc_retrieve_transaction_obj(chan, query->writehandle[dsn]))) {
|
||||
transactional = 1;
|
||||
} else {
|
||||
obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
|
||||
transactional = 0;
|
||||
}
|
||||
|
||||
if (obj && (stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(buf)))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj && !transactional) {
|
||||
|
@ -343,9 +344,27 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
|
|||
if (stmt && rows == 0 && ast_str_strlen(insertbuf) != 0) {
|
||||
SQLCloseCursor(stmt);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
for (dsn = 0; dsn < 5; dsn++) {
|
||||
if (obj && !transactional) {
|
||||
ast_odbc_release_obj(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
for (transactional = 0, dsn = 0; dsn < 5; dsn++) {
|
||||
if (!ast_strlen_zero(query->writehandle[dsn])) {
|
||||
obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
|
||||
if (transactional) {
|
||||
/* This can only happen second time through or greater. */
|
||||
ast_log(LOG_WARNING, "Transactions do not work well with multiple DSNs for 'writehandle'\n");
|
||||
} else if (obj) {
|
||||
ast_odbc_release_obj(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
|
||||
if ((obj = ast_odbc_retrieve_transaction_obj(chan, query->writehandle[dsn]))) {
|
||||
transactional = 1;
|
||||
} else {
|
||||
obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
|
||||
transactional = 0;
|
||||
}
|
||||
if (obj) {
|
||||
stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(insertbuf));
|
||||
}
|
||||
|
@ -355,8 +374,6 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co
|
|||
SQLRowCount(stmt, &rows);
|
||||
break;
|
||||
}
|
||||
ast_odbc_release_obj(obj);
|
||||
obj = NULL;
|
||||
}
|
||||
} else if (stmt) {
|
||||
status = "SUCCESS";
|
||||
|
@ -589,7 +606,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha
|
|||
|
||||
if (y == 0) {
|
||||
char colname[256];
|
||||
SQLULEN maxcol;
|
||||
SQLULEN maxcol = 0;
|
||||
|
||||
res = SQLDescribeCol(stmt, x + 1, (unsigned char *)colname, sizeof(colname), &collength, NULL, &maxcol, NULL, NULL);
|
||||
ast_debug(3, "Got collength of %d and maxcol of %d for column '%s' (offset %d)\n", (int)collength, (int)maxcol, colname, x);
|
||||
|
@ -1197,6 +1214,8 @@ static char *cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args
|
|||
}
|
||||
for (;;) {
|
||||
for (x = 0; x < colcount; x++) {
|
||||
maxcol = 0;
|
||||
|
||||
res = SQLDescribeCol(stmt, x + 1, (unsigned char *)colname, sizeof(colname), &collength, NULL, &maxcol, NULL, NULL);
|
||||
if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
|
||||
snprintf(colname, sizeof(colname), "field%d", x);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2007, Digium, Inc.
|
||||
* Copyright (C) 2011, Digium, Inc.
|
||||
*
|
||||
* Joshua Colp <jcolp@digium.com>
|
||||
*
|
||||
|
@ -35,6 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/audiohook.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
/*** DOCUMENTATION
|
||||
<function name="VOLUME" language="en_US">
|
||||
|
@ -45,6 +46,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
<parameter name="direction" required="true">
|
||||
<para>Must be <literal>TX</literal> or <literal>RX</literal>.</para>
|
||||
</parameter>
|
||||
<parameter name="options">
|
||||
<optionlist>
|
||||
<option name="p">
|
||||
<para>Enable DTMF volume control</para>
|
||||
</option>
|
||||
</optionlist>
|
||||
</parameter>
|
||||
</syntax>
|
||||
<description>
|
||||
<para>The VOLUME function can be used to increase or decrease the <literal>tx</literal> or
|
||||
|
@ -52,6 +60,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
<para>For example:</para>
|
||||
<para>Set(VOLUME(TX)=3)</para>
|
||||
<para>Set(VOLUME(RX)=2)</para>
|
||||
<para>Set(VOLUME(TX,p)=3)</para>
|
||||
<para>Set(VOLUME(RX,p)=3></para>
|
||||
</description>
|
||||
</function>
|
||||
***/
|
||||
|
@ -60,8 +70,17 @@ struct volume_information {
|
|||
struct ast_audiohook audiohook;
|
||||
int tx_gain;
|
||||
int rx_gain;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
enum volume_flags {
|
||||
VOLUMEFLAG_CHANGE = (1 << 1),
|
||||
};
|
||||
|
||||
AST_APP_OPTIONS(volume_opts, {
|
||||
AST_APP_OPTION('p', VOLUMEFLAG_CHANGE),
|
||||
});
|
||||
|
||||
static void destroy_callback(void *data)
|
||||
{
|
||||
struct volume_information *vi = data;
|
||||
|
@ -96,18 +115,23 @@ static int volume_callback(struct ast_audiohook *audiohook, struct ast_channel *
|
|||
vi = datastore->data;
|
||||
|
||||
/* If this is DTMF then allow them to increase/decrease the gains */
|
||||
if (frame->frametype == AST_FRAME_DTMF) {
|
||||
/* Only use DTMF coming from the source... not going to it */
|
||||
if (direction != AST_AUDIOHOOK_DIRECTION_READ)
|
||||
return 0;
|
||||
if (frame->subclass.integer == '*') {
|
||||
vi->tx_gain += 1;
|
||||
vi->rx_gain += 1;
|
||||
} else if (frame->subclass.integer == '#') {
|
||||
vi->tx_gain -= 1;
|
||||
vi->rx_gain -= 1;
|
||||
if (ast_test_flag(vi, VOLUMEFLAG_CHANGE)) {
|
||||
if (frame->frametype == AST_FRAME_DTMF) {
|
||||
/* Only use DTMF coming from the source... not going to it */
|
||||
if (direction != AST_AUDIOHOOK_DIRECTION_READ)
|
||||
return 0;
|
||||
if (frame->subclass.integer == '*') {
|
||||
vi->tx_gain += 1;
|
||||
vi->rx_gain += 1;
|
||||
} else if (frame->subclass.integer == '#') {
|
||||
vi->tx_gain -= 1;
|
||||
vi->rx_gain -= 1;
|
||||
}
|
||||
}
|
||||
} else if (frame->frametype == AST_FRAME_VOICE) {
|
||||
}
|
||||
|
||||
|
||||
if (frame->frametype == AST_FRAME_VOICE) {
|
||||
/* Based on direction of frame grab the gain, and confirm it is applicable */
|
||||
if (!(gain = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? &vi->rx_gain : &vi->tx_gain) || !*gain)
|
||||
return 0;
|
||||
|
@ -124,7 +148,18 @@ static int volume_write(struct ast_channel *chan, const char *cmd, char *data, c
|
|||
struct volume_information *vi = NULL;
|
||||
int is_new = 0;
|
||||
|
||||
/* Separate options from argument */
|
||||
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(direction);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, data);
|
||||
|
||||
ast_channel_lock(chan);
|
||||
if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) {
|
||||
ast_channel_unlock(chan);
|
||||
/* Allocate a new datastore to hold the reference to this volume and audiohook information */
|
||||
if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL)))
|
||||
return 0;
|
||||
|
@ -137,21 +172,42 @@ static int volume_write(struct ast_channel *chan, const char *cmd, char *data, c
|
|||
ast_set_flag(&vi->audiohook, AST_AUDIOHOOK_WANTS_DTMF);
|
||||
is_new = 1;
|
||||
} else {
|
||||
ast_channel_unlock(chan);
|
||||
vi = datastore->data;
|
||||
}
|
||||
|
||||
/* Adjust gain on volume information structure */
|
||||
if (!strcasecmp(data, "tx"))
|
||||
vi->tx_gain = atoi(value);
|
||||
else if (!strcasecmp(data, "rx"))
|
||||
if (ast_strlen_zero(args.direction)) {
|
||||
ast_log(LOG_ERROR, "Direction must be specified for VOLUME function\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcasecmp(args.direction, "tx")) {
|
||||
vi->tx_gain = atoi(value);
|
||||
} else if (!strcasecmp(args.direction, "rx")) {
|
||||
vi->rx_gain = atoi(value);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
|
||||
}
|
||||
|
||||
if (is_new) {
|
||||
datastore->data = vi;
|
||||
ast_channel_lock(chan);
|
||||
ast_channel_datastore_add(chan, datastore);
|
||||
ast_channel_unlock(chan);
|
||||
ast_audiohook_attach(chan, &vi->audiohook);
|
||||
}
|
||||
|
||||
/* Add Option data to struct */
|
||||
|
||||
if (!ast_strlen_zero(args.options)) {
|
||||
struct ast_flags flags = { 0 };
|
||||
ast_app_parse_options(volume_opts, &flags, &data, args.options);
|
||||
vi->flags = flags.flags;
|
||||
} else {
|
||||
vi->flags = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,17 @@ int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohoo
|
|||
*/
|
||||
struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format);
|
||||
|
||||
/*! \brief Reads a frame in from the audiohook structure in mixed audio mode and copies read and write frame data to provided arguments.
|
||||
* \param audiohook Audiohook structure
|
||||
* \param samples Number of samples wanted
|
||||
* \param direction Direction the audio frame came from
|
||||
* \param format Format of frame remote side wants back
|
||||
* \param ast_frame read_frame - if available, we'll copy the read buffer to this.
|
||||
* \param ast_frame write_frame - if available, we'll copy the write buffer to this.
|
||||
* \return Returns frame on success, NULL on failure
|
||||
*/
|
||||
struct ast_frame *ast_audiohook_read_frame_all(struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame);
|
||||
|
||||
/*! \brief Attach audiohook to channel
|
||||
* \param chan Channel
|
||||
* \param audiohook Audiohook structure
|
||||
|
|
|
@ -1098,10 +1098,6 @@
|
|||
/* Build chan_misdn for mISDN 1.2 or later. */
|
||||
#undef MISDN_1_2
|
||||
|
||||
/* Define to 1 if your system has a version of flex that does not check the
|
||||
return value of fwrite. */
|
||||
#undef NEED_FLEX_FWRITE_WORKAROUND
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ struct ast_calendar {
|
|||
AST_STRING_FIELD(notify_app); /*!< Optional dialplan app to execute for notification */
|
||||
AST_STRING_FIELD(notify_appdata); /*!< Optional arguments for dialplan app */
|
||||
);
|
||||
struct ast_variable *vars; /*!< Channel variables to pass to notification channel */
|
||||
int autoreminder; /*!< If set, override any calendar_tech specific notification times and use this time (in mins) */
|
||||
int notify_waittime; /*!< Maxiumum time to allow for a notification attempt */
|
||||
int refresh; /*!< When to refresh the calendar events */
|
||||
|
|
|
@ -65,11 +65,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/channel.h"
|
||||
#endif
|
||||
|
||||
#ifdef NEED_FLEX_FWRITE_WORKAROUND
|
||||
/*!\note Some versions of Flex use fwrite without checking its return value, which
|
||||
* is a warning on some compilers. Therefore, we use this workaround, to trick
|
||||
* the compiler into suppressing this warning. */
|
||||
#define fwrite(a,b,c,d) do { int __res = fwrite(a,b,c,d); (__res); } while (0)
|
||||
/* Conditionally redefine the macro from flex 2.5.35, in case someone uses flex <2.5.35 to regenerate this file. */
|
||||
#ifndef ECHO
|
||||
#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
|
||||
#endif
|
||||
|
||||
enum valtype {
|
||||
|
|
|
@ -559,11 +559,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
#include "asterisk/channel.h"
|
||||
#endif
|
||||
|
||||
#ifdef NEED_FLEX_FWRITE_WORKAROUND
|
||||
/*!\note Some versions of Flex use fwrite without checking its return value, which
|
||||
* is a warning on some compilers. Therefore, we use this workaround, to trick
|
||||
* the compiler into suppressing this warning. */
|
||||
#define fwrite(a,b,c,d) do { int __res = fwrite(a,b,c,d); (__res); } while (0)
|
||||
/* Conditionally redefine the macro from flex 2.5.35, in case someone uses flex <2.5.35 to regenerate this file. */
|
||||
#ifndef ECHO
|
||||
#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
|
||||
#endif
|
||||
|
||||
enum valtype {
|
||||
|
@ -611,7 +609,7 @@ int ast_yyget_column(yyscan_t yyscanner);
|
|||
static int curlycount = 0;
|
||||
static char *expr2_token_subst(const char *mess);
|
||||
|
||||
#line 613 "ast_expr2f.c"
|
||||
#line 611 "ast_expr2f.c"
|
||||
|
||||
#define INITIAL 0
|
||||
#define var 1
|
||||
|
@ -859,10 +857,10 @@ YY_DECL
|
|||
register int yy_act;
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
|
||||
#line 132 "ast_expr2.fl"
|
||||
#line 130 "ast_expr2.fl"
|
||||
|
||||
|
||||
#line 864 "ast_expr2f.c"
|
||||
#line 862 "ast_expr2f.c"
|
||||
|
||||
yylval = yylval_param;
|
||||
|
||||
|
@ -953,132 +951,132 @@ do_action: /* This label is used only to access EOF actions. */
|
|||
|
||||
case 1:
|
||||
YY_RULE_SETUP
|
||||
#line 134 "ast_expr2.fl"
|
||||
#line 132 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_OR;}
|
||||
YY_BREAK
|
||||
case 2:
|
||||
YY_RULE_SETUP
|
||||
#line 135 "ast_expr2.fl"
|
||||
#line 133 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_AND;}
|
||||
YY_BREAK
|
||||
case 3:
|
||||
YY_RULE_SETUP
|
||||
#line 136 "ast_expr2.fl"
|
||||
#line 134 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_EQ;}
|
||||
YY_BREAK
|
||||
case 4:
|
||||
YY_RULE_SETUP
|
||||
#line 137 "ast_expr2.fl"
|
||||
#line 135 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_OR;}
|
||||
YY_BREAK
|
||||
case 5:
|
||||
YY_RULE_SETUP
|
||||
#line 138 "ast_expr2.fl"
|
||||
#line 136 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_AND;}
|
||||
YY_BREAK
|
||||
case 6:
|
||||
YY_RULE_SETUP
|
||||
#line 139 "ast_expr2.fl"
|
||||
#line 137 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_EQ;}
|
||||
YY_BREAK
|
||||
case 7:
|
||||
YY_RULE_SETUP
|
||||
#line 140 "ast_expr2.fl"
|
||||
#line 138 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_EQTILDE;}
|
||||
YY_BREAK
|
||||
case 8:
|
||||
YY_RULE_SETUP
|
||||
#line 141 "ast_expr2.fl"
|
||||
#line 139 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_TILDETILDE;}
|
||||
YY_BREAK
|
||||
case 9:
|
||||
YY_RULE_SETUP
|
||||
#line 142 "ast_expr2.fl"
|
||||
#line 140 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_GT;}
|
||||
YY_BREAK
|
||||
case 10:
|
||||
YY_RULE_SETUP
|
||||
#line 143 "ast_expr2.fl"
|
||||
#line 141 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_LT;}
|
||||
YY_BREAK
|
||||
case 11:
|
||||
YY_RULE_SETUP
|
||||
#line 144 "ast_expr2.fl"
|
||||
#line 142 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_GE;}
|
||||
YY_BREAK
|
||||
case 12:
|
||||
YY_RULE_SETUP
|
||||
#line 145 "ast_expr2.fl"
|
||||
#line 143 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_LE;}
|
||||
YY_BREAK
|
||||
case 13:
|
||||
YY_RULE_SETUP
|
||||
#line 146 "ast_expr2.fl"
|
||||
#line 144 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_NE;}
|
||||
YY_BREAK
|
||||
case 14:
|
||||
YY_RULE_SETUP
|
||||
#line 147 "ast_expr2.fl"
|
||||
#line 145 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_PLUS;}
|
||||
YY_BREAK
|
||||
case 15:
|
||||
YY_RULE_SETUP
|
||||
#line 148 "ast_expr2.fl"
|
||||
#line 146 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_COMMA;}
|
||||
YY_BREAK
|
||||
case 16:
|
||||
YY_RULE_SETUP
|
||||
#line 149 "ast_expr2.fl"
|
||||
#line 147 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_MINUS;}
|
||||
YY_BREAK
|
||||
case 17:
|
||||
YY_RULE_SETUP
|
||||
#line 150 "ast_expr2.fl"
|
||||
#line 148 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_MULT;}
|
||||
YY_BREAK
|
||||
case 18:
|
||||
YY_RULE_SETUP
|
||||
#line 151 "ast_expr2.fl"
|
||||
#line 149 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_DIV;}
|
||||
YY_BREAK
|
||||
case 19:
|
||||
YY_RULE_SETUP
|
||||
#line 152 "ast_expr2.fl"
|
||||
#line 150 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_MOD;}
|
||||
YY_BREAK
|
||||
case 20:
|
||||
YY_RULE_SETUP
|
||||
#line 153 "ast_expr2.fl"
|
||||
#line 151 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_COND;}
|
||||
YY_BREAK
|
||||
case 21:
|
||||
YY_RULE_SETUP
|
||||
#line 154 "ast_expr2.fl"
|
||||
#line 152 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_COMPL;}
|
||||
YY_BREAK
|
||||
case 22:
|
||||
YY_RULE_SETUP
|
||||
#line 155 "ast_expr2.fl"
|
||||
#line 153 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_COLON;}
|
||||
YY_BREAK
|
||||
case 23:
|
||||
YY_RULE_SETUP
|
||||
#line 156 "ast_expr2.fl"
|
||||
#line 154 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
|
||||
YY_BREAK
|
||||
case 24:
|
||||
YY_RULE_SETUP
|
||||
#line 157 "ast_expr2.fl"
|
||||
#line 155 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_LP;}
|
||||
YY_BREAK
|
||||
case 25:
|
||||
YY_RULE_SETUP
|
||||
#line 158 "ast_expr2.fl"
|
||||
#line 156 "ast_expr2.fl"
|
||||
{ SET_COLUMNS; SET_STRING; return TOK_RP;}
|
||||
YY_BREAK
|
||||
case 26:
|
||||
YY_RULE_SETUP
|
||||
#line 159 "ast_expr2.fl"
|
||||
#line 157 "ast_expr2.fl"
|
||||
{
|
||||
/* gather the contents of ${} expressions, with trailing stuff,
|
||||
* into a single TOKEN.
|
||||
|
@ -1091,24 +1089,24 @@ YY_RULE_SETUP
|
|||
YY_BREAK
|
||||
case 27:
|
||||
YY_RULE_SETUP
|
||||
#line 169 "ast_expr2.fl"
|
||||
#line 167 "ast_expr2.fl"
|
||||
{}
|
||||
YY_BREAK
|
||||
case 28:
|
||||
/* rule 28 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 170 "ast_expr2.fl"
|
||||
#line 168 "ast_expr2.fl"
|
||||
{SET_COLUMNS; SET_STRING; return TOKEN;}
|
||||
YY_BREAK
|
||||
case 29:
|
||||
/* rule 29 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 172 "ast_expr2.fl"
|
||||
#line 170 "ast_expr2.fl"
|
||||
{/* what to do with eol */}
|
||||
YY_BREAK
|
||||
case 30:
|
||||
YY_RULE_SETUP
|
||||
#line 173 "ast_expr2.fl"
|
||||
#line 171 "ast_expr2.fl"
|
||||
{
|
||||
SET_COLUMNS;
|
||||
/* the original behavior of the expression parser was
|
||||
|
@ -1121,7 +1119,7 @@ YY_RULE_SETUP
|
|||
case 31:
|
||||
/* rule 31 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 182 "ast_expr2.fl"
|
||||
#line 180 "ast_expr2.fl"
|
||||
{
|
||||
SET_COLUMNS;
|
||||
SET_STRING;
|
||||
|
@ -1131,7 +1129,7 @@ YY_RULE_SETUP
|
|||
case 32:
|
||||
/* rule 32 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 188 "ast_expr2.fl"
|
||||
#line 186 "ast_expr2.fl"
|
||||
{
|
||||
curlycount = 0;
|
||||
BEGIN(var);
|
||||
|
@ -1141,7 +1139,7 @@ YY_RULE_SETUP
|
|||
case 33:
|
||||
/* rule 33 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 194 "ast_expr2.fl"
|
||||
#line 192 "ast_expr2.fl"
|
||||
{
|
||||
curlycount--;
|
||||
if (curlycount < 0) {
|
||||
|
@ -1155,7 +1153,7 @@ YY_RULE_SETUP
|
|||
case 34:
|
||||
/* rule 34 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 204 "ast_expr2.fl"
|
||||
#line 202 "ast_expr2.fl"
|
||||
{
|
||||
curlycount++;
|
||||
yymore();
|
||||
|
@ -1163,7 +1161,7 @@ YY_RULE_SETUP
|
|||
YY_BREAK
|
||||
case 35:
|
||||
YY_RULE_SETUP
|
||||
#line 210 "ast_expr2.fl"
|
||||
#line 208 "ast_expr2.fl"
|
||||
{
|
||||
BEGIN(0);
|
||||
SET_COLUMNS;
|
||||
|
@ -1173,7 +1171,7 @@ YY_RULE_SETUP
|
|||
YY_BREAK
|
||||
case 36:
|
||||
YY_RULE_SETUP
|
||||
#line 217 "ast_expr2.fl"
|
||||
#line 215 "ast_expr2.fl"
|
||||
{
|
||||
curlycount = 0;
|
||||
BEGIN(var);
|
||||
|
@ -1183,7 +1181,7 @@ YY_RULE_SETUP
|
|||
case 37:
|
||||
/* rule 37 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 223 "ast_expr2.fl"
|
||||
#line 221 "ast_expr2.fl"
|
||||
{
|
||||
char c = yytext[yyleng-1];
|
||||
BEGIN(0);
|
||||
|
@ -1194,7 +1192,7 @@ YY_RULE_SETUP
|
|||
}
|
||||
YY_BREAK
|
||||
case YY_STATE_EOF(trail):
|
||||
#line 232 "ast_expr2.fl"
|
||||
#line 230 "ast_expr2.fl"
|
||||
{
|
||||
BEGIN(0);
|
||||
SET_COLUMNS;
|
||||
|
@ -1205,10 +1203,10 @@ case YY_STATE_EOF(trail):
|
|||
YY_BREAK
|
||||
case 38:
|
||||
YY_RULE_SETUP
|
||||
#line 240 "ast_expr2.fl"
|
||||
#line 238 "ast_expr2.fl"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 1210 "ast_expr2f.c"
|
||||
#line 1208 "ast_expr2f.c"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
case YY_STATE_EOF(var):
|
||||
yyterminate();
|
||||
|
@ -2384,7 +2382,7 @@ void *ast_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
|
|||
|
||||
#define YYTABLES_NAME "yytables"
|
||||
|
||||
#line 240 "ast_expr2.fl"
|
||||
#line 238 "ast_expr2.fl"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3646,7 +3646,7 @@ int main(int argc, char *argv[])
|
|||
ast_copy_string(canary_binary, argv[0], sizeof(canary_binary));
|
||||
if ((lastslash = strrchr(canary_binary, '/'))) {
|
||||
ast_copy_string(lastslash + 1, "astcanary", sizeof(canary_binary) + canary_binary - (lastslash + 1));
|
||||
execl(canary_binary, "astcanary", canary_filename, (char *)NULL);
|
||||
execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
|
||||
}
|
||||
|
||||
/* Should never happen */
|
||||
|
|
|
@ -238,7 +238,7 @@ static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audio
|
|||
return ast_frdup(&frame);
|
||||
}
|
||||
|
||||
static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples)
|
||||
static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples, struct ast_frame **read_reference, struct ast_frame **write_reference)
|
||||
{
|
||||
int i = 0, usable_read, usable_write;
|
||||
short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
|
||||
|
@ -311,16 +311,27 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
|
|||
ast_debug(1, "Failed to get %d samples from write factory %p\n", (int)samples, &audiohook->write_factory);
|
||||
|
||||
/* Basically we figure out which buffer to use... and if mixing can be done here */
|
||||
if (!read_buf && !write_buf)
|
||||
return NULL;
|
||||
else if (read_buf && write_buf) {
|
||||
for (i = 0, data1 = read_buf, data2 = write_buf; i < samples; i++, data1++, data2++)
|
||||
if (read_buf && read_reference) {
|
||||
frame.data.ptr = buf1;
|
||||
*read_reference = ast_frdup(&frame);
|
||||
}
|
||||
if (write_buf && write_reference) {
|
||||
frame.data.ptr = buf2;
|
||||
*write_reference = ast_frdup(&frame);
|
||||
}
|
||||
|
||||
if (read_buf && write_buf) {
|
||||
for (i = 0, data1 = read_buf, data2 = write_buf; i < samples; i++, data1++, data2++) {
|
||||
ast_slinear_saturated_add(data1, data2);
|
||||
}
|
||||
final_buf = buf1;
|
||||
} else if (read_buf)
|
||||
} else if (read_buf) {
|
||||
final_buf = buf1;
|
||||
else if (write_buf)
|
||||
} else if (write_buf) {
|
||||
final_buf = buf2;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make the final buffer part of the frame, so it gets duplicated fine */
|
||||
frame.data.ptr = final_buf;
|
||||
|
@ -329,14 +340,7 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
|
|||
return ast_frdup(&frame);
|
||||
}
|
||||
|
||||
/*! \brief Reads a frame in from the audiohook structure
|
||||
* \param audiohook Audiohook structure
|
||||
* \param samples Number of samples wanted in requested output format
|
||||
* \param direction Direction the audio frame came from
|
||||
* \param format Format of frame remote side wants back
|
||||
* \return Returns frame on success, NULL on failure
|
||||
*/
|
||||
struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
|
||||
static struct ast_frame *audiohook_read_frame_helper(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
|
||||
{
|
||||
struct ast_frame *read_frame = NULL, *final_frame = NULL;
|
||||
struct ast_format tmp_fmt;
|
||||
|
@ -352,10 +356,10 @@ struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size
|
|||
samples_converted = samples * (ast_format_rate(format) / (float) audiohook->hook_internal_samp_rate);
|
||||
}
|
||||
|
||||
if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
|
||||
audiohook_read_frame_both(audiohook, samples_converted) :
|
||||
audiohook_read_frame_single(audiohook, samples_converted, direction)))) {
|
||||
return NULL;
|
||||
if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
|
||||
audiohook_read_frame_both(audiohook, samples_converted, read_reference, write_reference) :
|
||||
audiohook_read_frame_single(audiohook, samples_converted, direction)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If they don't want signed linear back out, we'll have to send it through the translation path */
|
||||
|
@ -383,6 +387,32 @@ struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size
|
|||
return final_frame;
|
||||
}
|
||||
|
||||
/*! \brief Reads a frame in from the audiohook structure
|
||||
* \param audiohook Audiohook structure
|
||||
* \param samples Number of samples wanted in requested output format
|
||||
* \param direction Direction the audio frame came from
|
||||
* \param format Format of frame remote side wants back
|
||||
* \return Returns frame on success, NULL on failure
|
||||
*/
|
||||
struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
|
||||
{
|
||||
return audiohook_read_frame_helper(audiohook, samples, direction, format, NULL, NULL);
|
||||
}
|
||||
|
||||
/*! \brief Reads a frame in from the audiohook structure
|
||||
* \param audiohook Audiohook structure
|
||||
* \param samples Number of samples wanted
|
||||
* \param direction Direction the audio frame came from
|
||||
* \param format Format of frame remote side wants back
|
||||
* \param read_frame frame pointer for copying read frame data
|
||||
* \param write_frame frame pointer for copying write frame data
|
||||
* \return Returns frame on success, NULL on failure
|
||||
*/
|
||||
struct ast_frame *ast_audiohook_read_frame_all(struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame)
|
||||
{
|
||||
return audiohook_read_frame_helper(audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, format, read_frame, write_frame);
|
||||
}
|
||||
|
||||
static void audiohook_list_set_samplerate_compatibility(struct ast_audiohook_list *audiohook_list)
|
||||
{
|
||||
struct ast_audiohook *ah = NULL;
|
||||
|
|
|
@ -568,9 +568,22 @@ int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, stru
|
|||
return -1;
|
||||
}
|
||||
if (res == 1) {
|
||||
/* Ignore invalid bytes */
|
||||
if (b > 0xff)
|
||||
continue;
|
||||
if (b > 0xff) {
|
||||
if (cid->sawflag != 5) {
|
||||
/* Ignore invalid bytes */
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* We can tollerate an error on the checksum character since the
|
||||
* checksum character is the last character in the message and
|
||||
* it validates the message.
|
||||
*
|
||||
* Remove character error flags.
|
||||
* Bit 8 : Parity error
|
||||
* Bit 9 : Framing error
|
||||
*/
|
||||
b &= 0xff;
|
||||
}
|
||||
switch (cid->sawflag) {
|
||||
case 0: /* Look for flag */
|
||||
if (b == 'U')
|
||||
|
|
|
@ -1496,6 +1496,11 @@ int ast_queue_hangup(struct ast_channel *chan)
|
|||
/* Yeah, let's not change a lock-critical value without locking */
|
||||
if (!ast_channel_trylock(chan)) {
|
||||
chan->_softhangup |= AST_SOFTHANGUP_DEV;
|
||||
manager_event(EVENT_FLAG_CALL, "HangupRequest",
|
||||
"Channel: %s\r\n"
|
||||
"Uniqueid: %s\r\n",
|
||||
chan->name,
|
||||
chan->uniqueid);
|
||||
ast_channel_unlock(chan);
|
||||
}
|
||||
return ast_queue_frame(chan, &f);
|
||||
|
@ -1515,6 +1520,13 @@ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
|
|||
if (cause < 0)
|
||||
f.data.uint32 = chan->hangupcause;
|
||||
|
||||
manager_event(EVENT_FLAG_CALL, "HangupRequest",
|
||||
"Channel: %s\r\n"
|
||||
"Uniqueid: %s\r\n"
|
||||
"Cause: %d\r\n",
|
||||
chan->name,
|
||||
chan->uniqueid,
|
||||
cause);
|
||||
ast_channel_unlock(chan);
|
||||
}
|
||||
|
||||
|
@ -2661,6 +2673,13 @@ int ast_softhangup(struct ast_channel *chan, int cause)
|
|||
|
||||
ast_channel_lock(chan);
|
||||
res = ast_softhangup_nolock(chan, cause);
|
||||
manager_event(EVENT_FLAG_CALL, "SoftHangupRequest",
|
||||
"Channel: %s\r\n"
|
||||
"Uniqueid: %s\r\n"
|
||||
"Cause: %d\r\n",
|
||||
chan->name,
|
||||
chan->uniqueid,
|
||||
cause);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
return res;
|
||||
|
|
160
main/features.c
160
main/features.c
|
@ -371,6 +371,12 @@ struct feature_group {
|
|||
|
||||
static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
|
||||
|
||||
typedef enum {
|
||||
FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
|
||||
FEATURE_INTERPRET_DO, /* Used by feature_interpret */
|
||||
FEATURE_INTERPRET_CHECK, /* Used by feature_check */
|
||||
} feature_interpret_op;
|
||||
|
||||
static char *parkedcall = "ParkedCall";
|
||||
|
||||
static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
|
||||
|
@ -2746,7 +2752,7 @@ static int remap_feature(const char *name, const char *value)
|
|||
*/
|
||||
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
|
||||
struct ast_bridge_config *config, const char *code, int sense, char *dynamic_features_buf,
|
||||
struct ast_flags *features, int operation, struct ast_call_feature *feature)
|
||||
struct ast_flags *features, feature_interpret_op operation, struct ast_call_feature *feature)
|
||||
{
|
||||
int x;
|
||||
struct feature_group *fg = NULL;
|
||||
|
@ -2756,7 +2762,7 @@ static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel
|
|||
int res = AST_FEATURE_RETURN_PASSDIGITS;
|
||||
int feature_detected = 0;
|
||||
|
||||
if (!(peer && chan && config) && operation) {
|
||||
if (!(peer && chan && config) && operation == FEATURE_INTERPRET_DO) {
|
||||
return -1; /* can not run feature operation */
|
||||
}
|
||||
|
||||
|
@ -2767,15 +2773,20 @@ static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel
|
|||
/* Feature is up for consideration */
|
||||
if (!strcmp(builtin_features[x].exten, code)) {
|
||||
ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
|
||||
if (operation) {
|
||||
if (operation == FEATURE_INTERPRET_CHECK) {
|
||||
res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
|
||||
} else if (operation == FEATURE_INTERPRET_DO) {
|
||||
res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
|
||||
}
|
||||
memcpy(feature, &builtin_features[x], sizeof(feature));
|
||||
if (feature) {
|
||||
memcpy(feature, &builtin_features[x], sizeof(feature));
|
||||
}
|
||||
feature_detected = 1;
|
||||
break;
|
||||
} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
|
||||
if (res == AST_FEATURE_RETURN_PASSDIGITS)
|
||||
if (res == AST_FEATURE_RETURN_PASSDIGITS) {
|
||||
res = AST_FEATURE_RETURN_STOREDIGITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2825,10 +2836,14 @@ static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel
|
|||
/* Feature is up for consideration */
|
||||
if (!strcmp(tmpfeature->exten, code)) {
|
||||
ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
|
||||
if (operation) {
|
||||
if (operation == FEATURE_INTERPRET_CHECK) {
|
||||
res = AST_FEATURE_RETURN_SUCCESS; /* We found something */
|
||||
} else if (operation == FEATURE_INTERPRET_DO) {
|
||||
res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
|
||||
}
|
||||
memcpy(feature, tmpfeature, sizeof(feature));
|
||||
if (feature) {
|
||||
memcpy(feature, tmpfeature, sizeof(feature));
|
||||
}
|
||||
if (res != AST_FEATURE_RETURN_KEEPTRYING) {
|
||||
AST_RWLIST_UNLOCK(&feature_list);
|
||||
break;
|
||||
|
@ -2876,13 +2891,19 @@ static int feature_interpret(struct ast_channel *chan, struct ast_channel *peer,
|
|||
|
||||
ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
|
||||
|
||||
return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
|
||||
return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, FEATURE_INTERPRET_DO, &feature);
|
||||
}
|
||||
|
||||
|
||||
int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, const char *code, struct ast_call_feature *feature) {
|
||||
|
||||
return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
|
||||
return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature);
|
||||
}
|
||||
|
||||
/*! \brief Check if a feature exists */
|
||||
static int feature_check(struct ast_channel *chan, struct ast_flags *features, char *code) {
|
||||
|
||||
return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_CHECK, NULL);
|
||||
}
|
||||
|
||||
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
|
||||
|
@ -3419,6 +3440,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
|
|||
int hasfeatures=0;
|
||||
int hadfeatures=0;
|
||||
int autoloopflag;
|
||||
int sendingdtmfdigit = 0;
|
||||
int we_disabled_peer_cdr = 0;
|
||||
struct ast_option_header *aoh;
|
||||
struct ast_cdr *bridge_cdr = NULL;
|
||||
|
@ -3427,6 +3449,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
|
|||
struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */
|
||||
struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
|
||||
struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
|
||||
struct ast_silence_generator *silgen = NULL;
|
||||
|
||||
if (chan && peer) {
|
||||
pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
|
||||
|
@ -3693,7 +3716,38 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
|
|||
break;
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
|
||||
/* eat it */
|
||||
struct ast_flags *cfg;
|
||||
char dtmfcode[2] = { f->subclass.integer, };
|
||||
size_t featurelen;
|
||||
|
||||
if (who == chan) {
|
||||
featurelen = strlen(chan_featurecode);
|
||||
cfg = &(config->features_caller);
|
||||
} else {
|
||||
featurelen = strlen(peer_featurecode);
|
||||
cfg = &(config->features_callee);
|
||||
}
|
||||
/* Take a peek if this (possibly) matches a feature. If not, just pass this
|
||||
* DTMF along untouched. If this is not the first digit of a multi-digit code
|
||||
* then we need to fall through and stream the characters if it matches */
|
||||
if (featurelen == 0
|
||||
&& feature_check(chan, cfg, &dtmfcode[0]) == AST_FEATURE_RETURN_PASSDIGITS) {
|
||||
if (option_debug > 3) {
|
||||
ast_log(LOG_DEBUG, "Passing DTMF through, since it is not a feature code\n");
|
||||
}
|
||||
ast_write(other, f);
|
||||
sendingdtmfdigit = 1;
|
||||
} else {
|
||||
/* If ast_opt_transmit_silence is set, then we need to make sure we are
|
||||
* transmitting something while we hold on to the DTMF waiting for a
|
||||
* feature. */
|
||||
if (!silgen && ast_opt_transmit_silence) {
|
||||
silgen = ast_channel_start_silence_generator(other);
|
||||
}
|
||||
if (option_debug > 3) {
|
||||
ast_log(LOG_DEBUG, "Not passing DTMF through, since it may be a feature code\n");
|
||||
}
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_DTMF) {
|
||||
char *featurecode;
|
||||
int sense;
|
||||
|
@ -3707,41 +3761,53 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
|
|||
sense = FEATURE_SENSE_PEER;
|
||||
featurecode = peer_featurecode;
|
||||
}
|
||||
/*! append the event to featurecode. we rely on the string being zero-filled, and
|
||||
* not overflowing it.
|
||||
* \todo XXX how do we guarantee the latter ?
|
||||
*/
|
||||
featurecode[strlen(featurecode)] = f->subclass.integer;
|
||||
/* Get rid of the frame before we start doing "stuff" with the channels */
|
||||
ast_frfree(f);
|
||||
f = NULL;
|
||||
config->feature_timer = 0;
|
||||
res = feature_interpret(chan, peer, config, featurecode, sense);
|
||||
switch(res) {
|
||||
case AST_FEATURE_RETURN_PASSDIGITS:
|
||||
ast_dtmf_stream(other, who, featurecode, 0, 0);
|
||||
/* Fall through */
|
||||
case AST_FEATURE_RETURN_SUCCESS:
|
||||
memset(featurecode, 0, sizeof(chan_featurecode));
|
||||
break;
|
||||
}
|
||||
if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
|
||||
res = 0;
|
||||
|
||||
if (sendingdtmfdigit == 1) {
|
||||
/* We let the BEGIN go through happily, so let's not bother with the END,
|
||||
* since we already know it's not something we bother with */
|
||||
ast_write(other, f);
|
||||
sendingdtmfdigit = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
|
||||
if (hadfeatures && !hasfeatures) {
|
||||
/* Feature completed or timed out */
|
||||
config->feature_timer = 0;
|
||||
} else if (hasfeatures) {
|
||||
if (config->timelimit) {
|
||||
/* No warning next time - we are waiting for future */
|
||||
ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
|
||||
/*! append the event to featurecode. we rely on the string being zero-filled, and
|
||||
* not overflowing it.
|
||||
* \todo XXX how do we guarantee the latter ?
|
||||
*/
|
||||
featurecode[strlen(featurecode)] = f->subclass.integer;
|
||||
/* Get rid of the frame before we start doing "stuff" with the channels */
|
||||
ast_frfree(f);
|
||||
f = NULL;
|
||||
if (silgen) {
|
||||
ast_channel_stop_silence_generator(other, silgen);
|
||||
silgen = NULL;
|
||||
}
|
||||
config->feature_timer = 0;
|
||||
res = feature_interpret(chan, peer, config, featurecode, sense);
|
||||
switch(res) {
|
||||
case AST_FEATURE_RETURN_PASSDIGITS:
|
||||
ast_dtmf_stream(other, who, featurecode, 0, 0);
|
||||
/* Fall through */
|
||||
case AST_FEATURE_RETURN_SUCCESS:
|
||||
memset(featurecode, 0, sizeof(chan_featurecode));
|
||||
break;
|
||||
}
|
||||
if (res >= AST_FEATURE_RETURN_PASSDIGITS) {
|
||||
res = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
|
||||
if (hadfeatures && !hasfeatures) {
|
||||
/* Feature completed or timed out */
|
||||
config->feature_timer = 0;
|
||||
} else if (hasfeatures) {
|
||||
if (config->timelimit) {
|
||||
/* No warning next time - we are waiting for future */
|
||||
ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
|
||||
}
|
||||
config->feature_start_time = ast_tvnow();
|
||||
config->feature_timer = featuredigittimeout;
|
||||
ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
|
||||
}
|
||||
config->feature_start_time = ast_tvnow();
|
||||
config->feature_timer = featuredigittimeout;
|
||||
ast_debug(1, "Set feature timer to %ld ms\n", config->feature_timer);
|
||||
}
|
||||
}
|
||||
if (f)
|
||||
|
@ -3749,7 +3815,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
|
|||
|
||||
}
|
||||
ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, NULL);
|
||||
before_you_go:
|
||||
|
||||
before_you_go:
|
||||
/* Just in case something weird happened and we didn't clean up the silence generator... */
|
||||
if (silgen) {
|
||||
ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);
|
||||
silgen = NULL;
|
||||
}
|
||||
|
||||
if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
|
||||
ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
|
||||
|
|
|
@ -962,6 +962,7 @@ struct mansession {
|
|||
struct ast_tcptls_session_instance *tcptls_session;
|
||||
FILE *f;
|
||||
int fd;
|
||||
int write_error:1;
|
||||
struct manager_custom_hook *hook;
|
||||
ast_mutex_t lock;
|
||||
};
|
||||
|
@ -1835,6 +1836,10 @@ int ast_hook_send_action(struct manager_custom_hook *hook, const char *msg)
|
|||
*/
|
||||
static int send_string(struct mansession *s, char *string)
|
||||
{
|
||||
int res;
|
||||
FILE *f = s->f ? s->f : s->session->f;
|
||||
int fd = s->f ? s->fd : s->session->fd;
|
||||
|
||||
/* It's a result from one of the hook's action invocation */
|
||||
if (s->hook) {
|
||||
/*
|
||||
|
@ -1843,11 +1848,13 @@ static int send_string(struct mansession *s, char *string)
|
|||
*/
|
||||
s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
|
||||
return 0;
|
||||
} else if (s->f) {
|
||||
return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->session->writetimeout);
|
||||
} else {
|
||||
return ast_careful_fwrite(s->session->f, s->session->fd, string, strlen(string), s->session->writetimeout);
|
||||
}
|
||||
|
||||
if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
|
||||
s->write_error = 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -4686,7 +4693,7 @@ static void *session_do(void *data)
|
|||
ao2_unlock(session);
|
||||
astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */
|
||||
for (;;) {
|
||||
if ((res = do_message(&s)) < 0) {
|
||||
if ((res = do_message(&s)) < 0 || s.write_error) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5852,7 +5859,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
|
|||
goto auth_callback_out;
|
||||
}
|
||||
|
||||
ast_str_append(&http_header, 0, "Content-type: text/%s", contenttype[format]);
|
||||
ast_str_append(&http_header, 0, "Content-type: text/%s\r\n", contenttype[format]);
|
||||
|
||||
if (format == FORMAT_XML) {
|
||||
ast_str_append(&out, 0, "<ajax-response>\n");
|
||||
|
|
|
@ -1234,10 +1234,22 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
|
|||
cs[1] = cs[2];
|
||||
}
|
||||
|
||||
if (glue0->update_peer(c0, NULL, NULL, NULL, 0, 0)) {
|
||||
if (ast_test_flag(c0, AST_FLAG_ZOMBIE)) {
|
||||
ast_debug(1, "Channel '%s' Zombie cleardown from bridge\n", c0->name);
|
||||
} else if (c0->tech_pvt != pvt0) {
|
||||
ast_debug(1, "Channel c0->'%s' pvt changed, in bridge with c1->'%s'\n", c0->name, c1->name);
|
||||
} else if (glue0 != ast_rtp_instance_get_glue(c0->tech->type)) {
|
||||
ast_debug(1, "Channel c0->'%s' technology changed, in bridge with c1->'%s'\n", c0->name, c1->name);
|
||||
} else if (glue0->update_peer(c0, NULL, NULL, NULL, 0, 0)) {
|
||||
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
|
||||
}
|
||||
if (glue1->update_peer(c1, NULL, NULL, NULL, 0, 0)) {
|
||||
if (ast_test_flag(c1, AST_FLAG_ZOMBIE)) {
|
||||
ast_debug(1, "Channel '%s' Zombie cleardown from bridge\n", c1->name);
|
||||
} else if (c1->tech_pvt != pvt1) {
|
||||
ast_debug(1, "Channel c1->'%s' pvt changed, in bridge with c0->'%s'\n", c1->name, c0->name);
|
||||
} else if (glue1 != ast_rtp_instance_get_glue(c1->tech->type)) {
|
||||
ast_debug(1, "Channel c1->'%s' technology changed, in bridge with c0->'%s'\n", c1->name, c0->name);
|
||||
} else if (glue1->update_peer(c1, NULL, NULL, NULL, 0, 0)) {
|
||||
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,8 +139,12 @@ static void *handle_tcptls_connection(void *data)
|
|||
* open a FILE * as appropriate.
|
||||
*/
|
||||
if (!tcptls_session->parent->tls_cfg) {
|
||||
tcptls_session->f = fdopen(tcptls_session->fd, "w+");
|
||||
setvbuf(tcptls_session->f, NULL, _IONBF, 0);
|
||||
if ((tcptls_session->f = fdopen(tcptls_session->fd, "w+"))) {
|
||||
if(setvbuf(tcptls_session->f, NULL, _IONBF, 0)) {
|
||||
fclose(tcptls_session->f);
|
||||
tcptls_session->f = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DO_SSL
|
||||
else if ( (tcptls_session->ssl = SSL_new(tcptls_session->parent->tls_cfg->ssl_ctx)) ) {
|
||||
|
|
|
@ -915,7 +915,7 @@ static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_
|
|||
AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
|
||||
int i;
|
||||
if (lock_info->num_locks) {
|
||||
ast_str_append(&str, 0, "=== Thread ID: %ld (%s)\n", (long) lock_info->thread_id,
|
||||
ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n", (long) lock_info->thread_id,
|
||||
lock_info->thread_name);
|
||||
pthread_mutex_lock(&lock_info->lock);
|
||||
for (i = 0; str && i < lock_info->num_locks; i++) {
|
||||
|
|
|
@ -100,6 +100,7 @@ AST_DECLARATION_AFTER_STATEMENT=@AST_DECLARATION_AFTER_STATEMENT@
|
|||
AST_NO_STRICT_OVERFLOW=@AST_NO_STRICT_OVERFLOW@
|
||||
AST_SHADOW_WARNINGS=@AST_SHADOW_WARNINGS@
|
||||
AST_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@
|
||||
AST_MARCH_NATIVE=@AST_MARCH_NATIVE@
|
||||
|
||||
ALSA_INCLUDE=@ALSA_INCLUDE@
|
||||
ALSA_LIB=@ALSA_LIB@
|
||||
|
|
|
@ -55,6 +55,26 @@ static int mtx_prof = -1; /* helps the standalone compile with the mtx_prof flag
|
|||
#include "asterisk/argdesc.h"
|
||||
#endif
|
||||
|
||||
/*** DOCUMENTATION
|
||||
<application name="AELSub" language="en_US">
|
||||
<synopsis>
|
||||
Launch subroutine built with AEL
|
||||
</synopsis>
|
||||
<syntax>
|
||||
<parameter name="routine" required="true">
|
||||
<para>Named subroutine to execute.</para>
|
||||
</parameter>
|
||||
<parameter name="args" required="false" />
|
||||
</syntax>
|
||||
<description>
|
||||
<para>Execute the named subroutine, defined in AEL, from another dialplan
|
||||
language, such as extensions.conf, Realtime extensions, or Lua.</para>
|
||||
<para>The purpose of this application is to provide a sane entry point into
|
||||
AEL subroutines, the implementation of which may change from time to time.</para>
|
||||
</description>
|
||||
</application>
|
||||
***/
|
||||
|
||||
/* these functions are in ../ast_expr2.fl */
|
||||
|
||||
#define DEBUG_READ (1 << 0)
|
||||
|
@ -108,6 +128,27 @@ static int aeldebug = 0;
|
|||
|
||||
/* interface stuff */
|
||||
|
||||
#ifndef STANDALONE
|
||||
static char *aelsub = "AELSub";
|
||||
|
||||
static int aelsub_exec(struct ast_channel *chan, const char *vdata)
|
||||
{
|
||||
char buf[256], *data = ast_strdupa(vdata);
|
||||
struct ast_app *gosub = pbx_findapp("Gosub");
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(name);
|
||||
AST_APP_ARG(args);
|
||||
);
|
||||
|
||||
if (gosub) {
|
||||
AST_STANDARD_RAW_ARGS(args, data);
|
||||
snprintf(buf, sizeof(buf), "%s,~~s~~,1(%s)", args.name, args.args);
|
||||
return pbx_exec(chan, gosub, buf);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if all the below are static, who cares if they are present? */
|
||||
|
||||
static int pbx_load_module(void)
|
||||
|
@ -224,12 +265,18 @@ static int unload_module(void)
|
|||
{
|
||||
ast_context_destroy(NULL, registrar);
|
||||
ast_cli_unregister_multiple(cli_ael, ARRAY_LEN(cli_ael));
|
||||
#ifndef STANDALONE
|
||||
ast_unregister_application(aelsub);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
ast_cli_register_multiple(cli_ael, ARRAY_LEN(cli_ael));
|
||||
#ifndef STANDALONE
|
||||
ast_register_application_xml(aelsub, aelsub_exec);
|
||||
#endif
|
||||
return (pbx_load_module());
|
||||
}
|
||||
|
||||
|
|
123
pbx/pbx_lua.c
123
pbx/pbx_lua.c
|
@ -58,6 +58,7 @@ static int lua_reload_extensions(lua_State *L);
|
|||
static void lua_free_extensions(void);
|
||||
static int lua_sort_extensions(lua_State *L);
|
||||
static int lua_register_switches(lua_State *L);
|
||||
static int lua_register_hints(lua_State *L);
|
||||
static int lua_extension_cmp(lua_State *L);
|
||||
static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func);
|
||||
static int lua_pbx_findapp(lua_State *L);
|
||||
|
@ -736,6 +737,9 @@ static int lua_error_function(lua_State *L)
|
|||
* backtrace to it */
|
||||
message_index = lua_gettop(L);
|
||||
|
||||
/* prepare to prepend a new line to the traceback */
|
||||
lua_pushliteral(L, "\n");
|
||||
|
||||
lua_getglobal(L, "debug");
|
||||
lua_getfield(L, -1, "traceback");
|
||||
lua_remove(L, -2); /* remove the 'debug' table */
|
||||
|
@ -747,6 +751,9 @@ static int lua_error_function(lua_State *L)
|
|||
|
||||
lua_call(L, 2, 1);
|
||||
|
||||
/* prepend the new line we prepared above */
|
||||
lua_concat(L, 2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -787,7 +794,11 @@ static int lua_sort_extensions(lua_State *L)
|
|||
int context_name = context - 1;
|
||||
int context_order;
|
||||
|
||||
/* copy the context_name to be used as the key for the
|
||||
* context_order table in the extensions_order table later */
|
||||
lua_pushvalue(L, context_name);
|
||||
|
||||
/* create the context_order table */
|
||||
lua_newtable(L);
|
||||
context_order = lua_gettop(L);
|
||||
|
||||
|
@ -886,6 +897,86 @@ static int lua_register_switches(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Register dialplan hints for our pbx_lua contexs.
|
||||
*
|
||||
* In the event of an error, an error string will be pushed onto the lua stack.
|
||||
*
|
||||
* \retval 0 success
|
||||
* \retval 1 failure
|
||||
*/
|
||||
static int lua_register_hints(lua_State *L)
|
||||
{
|
||||
int hints;
|
||||
struct ast_context *con = NULL;
|
||||
|
||||
/* create the hash table for our contexts */
|
||||
/* XXX do we ever need to destroy this? pbx_config does not */
|
||||
if (!local_table)
|
||||
local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
|
||||
|
||||
/* load the 'hints' table */
|
||||
lua_getglobal(L, "hints");
|
||||
hints = lua_gettop(L);
|
||||
if (lua_isnil(L, -1)) {
|
||||
/* hints table not found, move along */
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iterate through the hints table and register each context and
|
||||
* the hints that go along with it
|
||||
*/
|
||||
for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) {
|
||||
int context = lua_gettop(L);
|
||||
int context_name = context - 1;
|
||||
const char *context_str = lua_tostring(L, context_name);
|
||||
|
||||
/* find or create this context */
|
||||
con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
|
||||
if (!con) {
|
||||
/* remove hints table and context key and value */
|
||||
lua_pop(L, 3);
|
||||
lua_pushstring(L, "Failed to find or create context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* register each hint */
|
||||
for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
|
||||
const char *hint_value = lua_tostring(L, -1);
|
||||
const char *hint_name;
|
||||
|
||||
/* the hint value is not a string, ignore it */
|
||||
if (!hint_value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy the name then convert it to a string */
|
||||
lua_pushvalue(L, -2);
|
||||
if (!(hint_name = lua_tostring(L, -1))) {
|
||||
/* ignore non-string value */
|
||||
lua_pop(L, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar)) {
|
||||
/* remove hints table, hint name, hint value,
|
||||
* key copy, context name, and contex table */
|
||||
lua_pop(L, 6);
|
||||
lua_pushstring(L, "Error creating hint\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* pop the name copy */
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the hints table */
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief [lua_CFunction] Compare two extensions (for access from lua, don't
|
||||
|
@ -920,6 +1011,7 @@ static int lua_extension_cmp(lua_State *L)
|
|||
static char *lua_read_extensions_file(lua_State *L, long *size)
|
||||
{
|
||||
FILE *f;
|
||||
int error_func;
|
||||
char *data;
|
||||
char *path = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
|
||||
sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
|
||||
|
@ -934,10 +1026,20 @@ static char *lua_read_extensions_file(lua_State *L, long *size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
fseek(f, 0l, SEEK_END);
|
||||
if (fseek(f, 0l, SEEK_END)) {
|
||||
fclose(f);
|
||||
lua_pushliteral(L, "error determining the size of the config file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*size = ftell(f);
|
||||
|
||||
fseek(f, 0l, SEEK_SET);
|
||||
if (fseek(f, 0l, SEEK_SET)) {
|
||||
*size = 0;
|
||||
fclose(f);
|
||||
lua_pushliteral(L, "error reading config file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(data = ast_malloc(*size))) {
|
||||
*size = 0;
|
||||
|
@ -947,18 +1049,27 @@ static char *lua_read_extensions_file(lua_State *L, long *size)
|
|||
}
|
||||
|
||||
if (fread(data, sizeof(char), *size, f) != *size) {
|
||||
ast_log(LOG_WARNING, "fread() failed: %s\n", strerror(errno));
|
||||
*size = 0;
|
||||
fclose(f);
|
||||
lua_pushliteral(L, "problem reading configuration file");
|
||||
return NULL;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
lua_pushcfunction(L, &lua_error_function);
|
||||
error_func = lua_gettop(L);
|
||||
|
||||
if (luaL_loadbuffer(L, data, *size, "extensions.lua")
|
||||
|| lua_pcall(L, 0, LUA_MULTRET, 0)
|
||||
|| lua_pcall(L, 0, LUA_MULTRET, error_func)
|
||||
|| lua_sort_extensions(L)
|
||||
|| lua_register_switches(L)) {
|
||||
|| lua_register_switches(L)
|
||||
|| lua_register_hints(L)) {
|
||||
ast_free(data);
|
||||
data = NULL;
|
||||
*size = 0;
|
||||
}
|
||||
|
||||
lua_remove(L, error_func);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1467,7 +1578,7 @@ static int load_module(void)
|
|||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Lua PBX Switch",
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Lua PBX Switch",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload,
|
||||
|
|
|
@ -313,6 +313,10 @@ static void calendar_destructor(void *obj)
|
|||
}
|
||||
ast_calendar_clear_events(cal);
|
||||
ast_string_field_free_memory(cal);
|
||||
if (cal->vars) {
|
||||
ast_variables_destroy(cal->vars);
|
||||
cal->vars = NULL;
|
||||
}
|
||||
ao2_ref(cal->events, -1);
|
||||
ao2_unlock(cal);
|
||||
}
|
||||
|
@ -369,7 +373,7 @@ static enum ast_device_state calendarstate(const char *data)
|
|||
static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *cat, const struct ast_calendar_tech *tech)
|
||||
{
|
||||
struct ast_calendar *cal;
|
||||
struct ast_variable *v;
|
||||
struct ast_variable *v, *last = NULL;
|
||||
int new_calendar = 0;
|
||||
|
||||
if (!(cal = find_calendar(cat))) {
|
||||
|
@ -423,6 +427,26 @@ static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *c
|
|||
cal->refresh = atoi(v->value);
|
||||
} else if (!strcasecmp(v->name, "timeframe")) {
|
||||
cal->timeframe = atoi(v->value);
|
||||
} else if (!strcasecmp(v->name, "setvar")) {
|
||||
char *name, *value;
|
||||
struct ast_variable *var;
|
||||
|
||||
if ((name = (value = ast_strdup(v->value)))) {
|
||||
strsep(&value, "=");
|
||||
if (value) {
|
||||
if ((var = ast_variable_new(ast_strip(name), ast_strip(value), ""))) {
|
||||
if (last) {
|
||||
last->next = var;
|
||||
} else {
|
||||
cal->vars = var;
|
||||
}
|
||||
last = var;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Malformed argument. Should be '%s: variable=value'\n", v->name);
|
||||
}
|
||||
ast_free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,10 +690,11 @@ static void *do_notify(void *data)
|
|||
{
|
||||
struct ast_calendar_event *event = data;
|
||||
struct ast_dial *dial = NULL;
|
||||
struct ast_str *apptext = NULL;
|
||||
struct ast_str *apptext = NULL, *tmpstr;
|
||||
struct ast_datastore *datastore;
|
||||
enum ast_dial_result res;
|
||||
struct ast_channel *chan = NULL;
|
||||
struct ast_variable *itervar;
|
||||
char *tech, *dest;
|
||||
char buf[8];
|
||||
|
||||
|
@ -720,6 +745,15 @@ static void *do_notify(void *data)
|
|||
ao2_ref(event, +1);
|
||||
res = ast_channel_datastore_add(chan, datastore);
|
||||
|
||||
if (!(tmpstr = ast_str_create(32))) {
|
||||
goto notify_cleanup;
|
||||
}
|
||||
|
||||
for (itervar = event->owner->vars; itervar; itervar = itervar->next) {
|
||||
ast_str_substitute_variables(&tmpstr, 0, chan, itervar->value);
|
||||
pbx_builtin_setvar_helper(chan, itervar->name, tmpstr->str);
|
||||
}
|
||||
|
||||
if (!(apptext = ast_str_create(32))) {
|
||||
goto notify_cleanup;
|
||||
}
|
||||
|
@ -751,6 +785,9 @@ notify_cleanup:
|
|||
if (apptext) {
|
||||
ast_free(apptext);
|
||||
}
|
||||
if (tmpstr) {
|
||||
ast_free(tmpstr);
|
||||
}
|
||||
if (dial) {
|
||||
ast_dial_destroy(dial);
|
||||
}
|
||||
|
@ -1522,7 +1559,7 @@ static char *handle_show_calendar(struct ast_cli_entry *e, int cmd, struct ast_c
|
|||
ast_cli(a->fd, FORMAT2, "Description", event->description);
|
||||
ast_cli(a->fd, FORMAT2, "Organizer", event->organizer);
|
||||
ast_cli(a->fd, FORMAT2, "Location", event->location);
|
||||
ast_cli(a->fd, FORMAT2, "Cartegories", event->categories);
|
||||
ast_cli(a->fd, FORMAT2, "Categories", event->categories);
|
||||
ast_cli(a->fd, "%-12.12s: %d\n", "Priority", event->priority);
|
||||
ast_cli(a->fd, FORMAT2, "UID", event->uid);
|
||||
ast_cli(a->fd, FORMAT2, "Start", epoch_to_string(buf, sizeof(buf), event->start));
|
||||
|
|
|
@ -238,6 +238,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl
|
|||
}
|
||||
for (x = 0; x < colcount; x++) {
|
||||
rowdata[0] = '\0';
|
||||
colsize = 0;
|
||||
collen = sizeof(coltitle);
|
||||
res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
|
||||
&datatype, &colsize, &decimaldigits, &nullable);
|
||||
|
@ -410,6 +411,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
|
|||
}
|
||||
for (x=0;x<colcount;x++) {
|
||||
rowdata[0] = '\0';
|
||||
colsize = 0;
|
||||
collen = sizeof(coltitle);
|
||||
res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
|
||||
&datatype, &colsize, &decimaldigits, &nullable);
|
||||
|
|
|
@ -932,6 +932,7 @@ static void set_channel_variables(struct ast_channel *chan, struct ast_fax_sessi
|
|||
pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
|
||||
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
|
||||
pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
|
||||
pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
|
||||
pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
|
||||
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
|
||||
|
||||
|
@ -1513,6 +1514,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||
/* initialize output channel variables */
|
||||
pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
|
||||
pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
|
||||
pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", NULL);
|
||||
pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
|
||||
pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
|
||||
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
|
||||
|
@ -1715,11 +1717,11 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||
info.context,
|
||||
info.exten,
|
||||
info.cid,
|
||||
pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"),
|
||||
pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"),
|
||||
pbx_builtin_getvar_helper(chan, "FAXPAGES"),
|
||||
pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"),
|
||||
pbx_builtin_getvar_helper(chan, "FAXBITRATE"),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
|
||||
args.filename);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
|
@ -1974,6 +1976,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||
/* initialize output channel variables */
|
||||
pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
|
||||
pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
|
||||
pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", NULL);
|
||||
pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
|
||||
pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
|
||||
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
|
||||
|
@ -2205,11 +2208,11 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||
info.context,
|
||||
info.exten,
|
||||
info.cid,
|
||||
pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"),
|
||||
pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"),
|
||||
pbx_builtin_getvar_helper(chan, "FAXPAGES"),
|
||||
pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"),
|
||||
pbx_builtin_getvar_helper(chan, "FAXBITRATE"),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
|
||||
S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
|
||||
filenames);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
|
|
|
@ -2490,7 +2490,7 @@ static void aji_handle_presence(struct aji_client *client, ikspak *pak)
|
|||
"Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d"
|
||||
"\r\nDescription: %s\r\n",
|
||||
client->name, pak->from->partial, found->resource, found->status,
|
||||
found->priority, found->description);
|
||||
found->priority, S_OR(found->description, ""));
|
||||
} else {
|
||||
manager_event(EVENT_FLAG_USER, "JabberStatus",
|
||||
"Account: %s\r\nJID: %s\r\nStatus: %d\r\n",
|
||||
|
|
|
@ -440,7 +440,7 @@ static int phoneprov_callback(struct ast_tcptls_session_instance *ser, const str
|
|||
}
|
||||
|
||||
http_header = ast_str_create(80);
|
||||
ast_str_set(&http_header, 0, "Content-type: %s",
|
||||
ast_str_set(&http_header, 0, "Content-type: %s\r\n",
|
||||
route->file->mime_type);
|
||||
|
||||
ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
|
||||
|
@ -504,7 +504,7 @@ static int phoneprov_callback(struct ast_tcptls_session_instance *ser, const str
|
|||
}
|
||||
|
||||
http_header = ast_str_create(80);
|
||||
ast_str_set(&http_header, 0, "Content-type: %s",
|
||||
ast_str_set(&http_header, 0, "Content-type: %s\r\n",
|
||||
route->file->mime_type);
|
||||
|
||||
if (!(result = ast_str_create(512))) {
|
||||
|
|
Reference in New Issue