dect
/
asterisk
Archived
13
0
Fork 0

Merge branch 'master' of 192.168.0.100:/repos/git/asterisk

This commit is contained in:
Patrick McHardy 2011-03-18 18:59:32 +01:00
commit b7347a56f8
51 changed files with 1806 additions and 1022 deletions

12
CHANGES
View File

@ -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 ----------------
------------------------------------------------------------------------------

View File

@ -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)

View File

@ -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

View File

@ -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, &parameters, 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,
&parameters, 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,
&parameters, sizeof(parameters));
}

View File

@ -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;

View File

@ -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:

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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

View File

@ -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. */

View File

@ -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 */

View File

@ -25,10 +25,6 @@
* \ingroup codecs
*/
/*** MODULEINFO
<depend>resample</depend>
***/
#include "asterisk.h"
#include "speex/speex_resampler.h"

View File

@ -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 =

View File

@ -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

View File

@ -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

View File

@ -197,3 +197,14 @@ extensions = {
};
}
hints = {
demo = {
[1000] = "SIP/1000";
[1001] = "SIP/1001";
};
default = {
["1234"] = "SIP/1234";
};
}

View File

@ -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

View File

@ -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

966
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -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>],

View File

@ -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>

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 {

View File

@ -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"

View File

@ -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 */

View File

@ -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;

View File

@ -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')

View File

@ -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;

View File

@ -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 */

View File

@ -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");

View File

@ -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);
}

View File

@ -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)) ) {

View File

@ -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++) {

View File

@ -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@

View File

@ -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());
}

View File

@ -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,

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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))) {