<p>Mark Murawski has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19264">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">chan_dahdi: Add DAHDIBusyOut<br><br>This feature will 'busy out' a DAHDI channel in the traditional<br>PSTN/ISDN sense of making the line completely unavailable for<br>both incoming and outgoing calls.<br><br>If DAHDIBusyOut is turned on for a DAHDI channel, it will appear<br>for all intents and purposes that the channel is in use until<br>the DAHDIBusyOut is turned off for that channel.<br><br>The status of DAHDIBusyOut will not survive across Asterisk restarts.<br><br>Change-Id: Ib75c87c554bb18b8f65be73b4474474e7e1877b7<br>---<br>M channels/chan_dahdi.c<br>M channels/chan_dahdi.h<br>2 files changed, 546 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/64/19264/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c</span><br><span>index b829aa4..cb21a0c 100644</span><br><span>--- a/channels/chan_dahdi.c</span><br><span>+++ b/channels/chan_dahdi.c</span><br><span>@@ -129,6 +129,8 @@</span><br><span> #include "chan_dahdi.h"</span><br><span> #include "dahdi/bridge_native_dahdi.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "regex.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*** DOCUMENTATION</span><br><span> <application name="DAHDISendKeypadFacility" language="en_US"></span><br><span> <synopsis></span><br><span>@@ -206,6 +208,24 @@</span><br><span> </example></span><br><span> </description></span><br><span> </function></span><br><span style="color: hsl(120, 100%, 40%);">+ <manager name="DAHDIBusyOut" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Set BusyOut Mode on DAHDI Channel(s).</span><br><span style="color: hsl(120, 100%, 40%);">+ </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="DAHDIChannel" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>DAHDI channel number(s) to change. Comma delimited list of channels, with ability for ranges. Example: 1,2,3 Example: 1-2,4-8</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="Mode" required="true"></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Boolean value, either enable or disable BusyOut</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </parameter></span><br><span style="color: hsl(120, 100%, 40%);">+ </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Enable or disable BusyOut on DAHDI channels.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <note><para>Valid only for analog channels.</para></note></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ </manager></span><br><span> <info name="CHANNEL" language="en_US" tech="DAHDI"></span><br><span> <enumlist></span><br><span> <enum name="dahdi_channel"></span><br><span>@@ -1112,6 +1132,9 @@</span><br><span> static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);</span><br><span> static int dahdi_devicestate(const char *data);</span><br><span> static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channels_busyout(const char *channel_list, int on, int *touched_channels);</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channel_busyout(struct dahdi_pvt *dahdi_chan, int on);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> static struct ast_channel_tech dahdi_tech = {</span><br><span> .type = "DAHDI",</span><br><span>@@ -5867,6 +5890,39 @@</span><br><span> #endif /* defined(HAVE_PRI) */</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static char *dahdi_busyout_app = "DAHDIBusyOut";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_busyout_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *params;</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(mode);</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "DAHDIBusyOut requires two arguments!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ params = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(args, params);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!args.channel) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "DAHDIBusyOut requires a channel number!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!args.mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "DAHDIBusyOut requires a mode!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #if defined(HAVE_PRI)</span><br><span> static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";</span><br><span> </span><br><span>@@ -8623,6 +8679,11 @@</span><br><span> p->subs[idx].f.src = "dahdi_read";</span><br><span> p->subs[idx].f.data.ptr = NULL;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (p->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_unlock(&p->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+ return &p->subs[idx].f;;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* make sure it sends initial key state as first frame */</span><br><span> if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))</span><br><span> {</span><br><span>@@ -9719,6 +9780,22 @@</span><br><span> </span><br><span> if (p->dsp)</span><br><span> ast_dsp_digitreset(p->dsp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_app *theapp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ theapp = pbx_findapp("Answer");</span><br><span style="color: hsl(120, 100%, 40%);">+ res = pbx_exec(chan, theapp, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "PBX exited non-zero\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ goto quit;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> switch (p->sig) {</span><br><span> case SIG_FEATD:</span><br><span> case SIG_FEATDMF:</span><br><span>@@ -11743,6 +11820,10 @@</span><br><span> break;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (i->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (thispass != lastpass) {</span><br><span> if (!found && ((i == last) || ((i == iflist) && !last))) {</span><br><span> last = i;</span><br><span>@@ -11894,6 +11975,7 @@</span><br><span> }</span><br><span> res = dahdi_get_event(i->subs[SUB_REAL].dfd);</span><br><span> ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Don't hold iflock while handling init events */</span><br><span> ast_mutex_unlock(&iflock);</span><br><span> if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {</span><br><span>@@ -15724,6 +15806,66 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int action_dahdibusyout(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *id = astman_get_header(m, "ActionID");</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *channel_arg = astman_get_header(m, "DAHDIChannel");</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *mode_arg = astman_get_header(m, "Mode");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ char action_id[256] = "";</span><br><span style="color: hsl(120, 100%, 40%);">+ int touched_channels[DAHDI_MAX_SPANS];</span><br><span style="color: hsl(120, 100%, 40%);">+ int touched_channels_num = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int on;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *on_txt;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(channel_arg)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "DAHDIBusyOut requires: DAHDIChannel");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(mode_arg)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_error(s, m, "DAHDIBusyOut requires: Mode");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ on = ast_true(mode_arg) ? 1 : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ on_txt = (on ? "On": "Off");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_send_listack(s, m, "Dahdi BusyOut channels will follow", "start");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_set_channels_busyout(channel_arg, on, touched_channels);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < DAHDI_MAX_SPANS; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (touched_channels[i] == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* touched_channels[channel] is going to be either -1 (failure), 0 (no change), 1 (set), or 2 (queued) */</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_append(s,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Event: DahdiBusyOutChannel\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "Channel: %d\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "BusyOut: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "%s"</span><br><span style="color: hsl(120, 100%, 40%);">+ "\r\n", i, (touched_channels[i] == 2 ? "Queued" : on_txt), action_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ touched_channels_num++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ astman_append(s,</span><br><span style="color: hsl(120, 100%, 40%);">+ "Event: DahdiBusyOutChannelListComplete\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "EventList: Complete\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "ListItems: %d\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ "%s"</span><br><span style="color: hsl(120, 100%, 40%);">+ "\r\n", touched_channels_num, action_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span> {</span><br><span> #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"</span><br><span>@@ -16372,6 +16514,55 @@</span><br><span> return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct dahdi_found_channel {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_ENTRY(dahdi_found_channel) entries; /*!< Next group */</span><br><span style="color: hsl(120, 100%, 40%);">+ int channel_num; /*!< Index into dahdi iflist */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_LIST_HEAD(dahdi_channel_list, dahdi_found_channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *dahdi_set_busy(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int on;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "dahdi set busyout";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+ "Usage: dahdi set busyout <chan#> <on|off>\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Sets/resets Busyout mode on a channel.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Changes take effect immediately.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <chan num> is the channel number\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <chan num> can also be a comma delimited list of channels, ex 1,4,7\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <chan num> can also be a range of channels, ex 1-8\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <chan num> can also be a mix of channels and ranges, ex 1-2,4-8\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <chan num> can also be 'all'\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " <on|off> Enable or disable Busyout mode?\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ ;</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc != 5)</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_true(a->argv[4]))</span><br><span style="color: hsl(120, 100%, 40%);">+ on = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (ast_false(a->argv[4]))</span><br><span style="color: hsl(120, 100%, 40%);">+ on = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_set_channels_busyout(a->argv[3], on, NULL) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Unable to find channels matching: %s\n", a->argv[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static struct ast_cli_entry dahdi_cli[] = {</span><br><span> AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),</span><br><span> AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),</span><br><span>@@ -16384,6 +16575,7 @@</span><br><span> AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),</span><br><span> AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),</span><br><span> AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(dahdi_set_busy, "Sets/resets Busyout mode on a channel"),</span><br><span> };</span><br><span> </span><br><span> #define TRANSFER 0</span><br><span>@@ -17705,6 +17897,7 @@</span><br><span> }</span><br><span> }</span><br><span> ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_unregister_application(dahdi_busyout_app);</span><br><span> ast_unregister_application(dahdi_send_keypad_facility_app);</span><br><span> #ifdef HAVE_PRI_PROG_W_CAUSE</span><br><span> ast_unregister_application(dahdi_send_callrerouting_facility_app);</span><br><span>@@ -17735,6 +17928,7 @@</span><br><span> ast_manager_unregister("DAHDIDNDon");</span><br><span> ast_manager_unregister("DAHDIShowChannels");</span><br><span> ast_manager_unregister("DAHDIRestart");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_manager_unregister("DAHDIBusyOut");</span><br><span> #if defined(HAVE_PRI)</span><br><span> ast_manager_unregister("PRIShowSpans");</span><br><span> ast_manager_unregister("PRIDebugSet");</span><br><span>@@ -19860,6 +20054,7 @@</span><br><span> }</span><br><span> pri_set_error(dahdi_pri_error);</span><br><span> pri_set_message(dahdi_pri_message);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_register_application_xml(dahdi_busyout_app, dahdi_busyout_exec);</span><br><span> ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);</span><br><span> #ifdef HAVE_PRI_PROG_W_CAUSE</span><br><span> ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);</span><br><span>@@ -19926,6 +20121,7 @@</span><br><span> ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);</span><br><span> ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);</span><br><span> ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_manager_register_xml("DAHDIBusyOut", 0, action_dahdibusyout);</span><br><span> #if defined(HAVE_PRI)</span><br><span> ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);</span><br><span> ast_manager_register_xml("PRIDebugSet", 0, action_pri_debug_set);</span><br><span>@@ -20058,6 +20254,322 @@</span><br><span> return(0);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Do the actual busyout thread creation</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note Lock dahdi_chan->lock before calling</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_busyout_start(struct dahdi_pvt *dahdi_chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int result;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_channel *chan;</span><br><span style="color: hsl(120, 100%, 40%);">+ pthread_t threadid;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busyout_queued = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((chan = dahdi_new(dahdi_chan, AST_STATE_RING, 0, SUB_REAL, 0, NULL, NULL, NULL))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Could not create channel to handle call\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->_busydetect = dahdi_chan->busydetect;</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busydetect = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busyout = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_devstate_changed(AST_STATE_BUSY, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/%d/busyout", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ result = _ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (result) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_hangup(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> Enabled BusyOut\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void *dahdi_set_channel_busyout_on_thread(void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Keep trying to set busyout on a channel that's currently in use</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+static void *dahdi_set_channel_busyout_on_thread(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *dahdi_chan = data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dahdi_chan->busyout_queued) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Busyout cancelled */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> BusyOut try thread done\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_chan->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Busyout already enabled */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> BusyOut try thread done\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_lock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dahdi_chan->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Current call finished */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_busyout_start(dahdi_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> BusyOut try thread done\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+ usleep(1000);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set busyout status on a list or range of channels</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param channel_list Comma delimited list of channels, may contain ranges</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param touched_channels pointer to integer array preallocated to the size of DAHDI_MAX_SPANS that holds the channels changed</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \detail</span><br><span style="color: hsl(120, 100%, 40%);">+ * touched_channels[channel] is going to be either -1 (failure), 0 (no change), 1 (set), or 2 (queued)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1"</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1,2"</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1,2-4"</span><br><span style="color: hsl(120, 100%, 40%);">+ * \example channel_list = "1-4,6-8"</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval >0 Count of channels that have had busyout status changed</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 No channel busyout status has been changed</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channels_busyout(const char *channel_list, int on, int *touched_channels)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int channel;</span><br><span style="color: hsl(120, 100%, 40%);">+ int channel_to;</span><br><span style="color: hsl(120, 100%, 40%);">+ int channels_touched = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int fail_match;</span><br><span style="color: hsl(120, 100%, 40%);">+ int have_comma_remaining;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ int match_comma_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ int match_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ int result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ char *channel_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *channel_arg_cur;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *match_start;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct dahdi_pvt *dahdi_chan = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *match_str = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *match_str_from = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *match_str_to = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ regex_t regexbuf_comma;</span><br><span style="color: hsl(120, 100%, 40%);">+ regex_t regexbuf_dash;</span><br><span style="color: hsl(120, 100%, 40%);">+ regmatch_t reg_m[DAHDI_MAX_SPANS];</span><br><span style="color: hsl(120, 100%, 40%);">+ int dahdi_channels_search[DAHDI_MAX_SPANS];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ channel_arg = ast_strdup(channel_list);</span><br><span style="color: hsl(120, 100%, 40%);">+ channel_arg_cur = channel_arg;</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&dahdi_channels_search, 0, sizeof(dahdi_channels_search));</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(touched_channels, 0, (DAHDI_MAX_SPANS * sizeof(int)));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "channels: %s\n", channel_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (regcomp(®exbuf_comma, "^([0-9-]+)(,|$)(.+)?", REG_EXTENDED)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should never fail */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Regex compile failed in dahdi_set_busy()\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (regcomp(®exbuf_dash, "^([0-9]+)-(.*)", REG_EXTENDED)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should never fail */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Regex compile failed in dahdi_set_busy()\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ do {</span><br><span style="color: hsl(120, 100%, 40%);">+ fail_match = regexec(®exbuf_comma, channel_arg_cur, 4, reg_m, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fail_match) {</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_ERROR, "regex match fail (%d): %s\n", fail_match, channel_arg_cur);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ match_start = (channel_arg_cur + reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+ match_comma_len = (reg_m[1].rm_eo - reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+ *(channel_arg_cur + match_comma_len) = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_set(&match_str, 0, "%s", match_start);</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "regex match: [%d:%d] %s (%d)\n", reg_m[1].rm_so, reg_m[1].rm_eo, ast_str_buffer(match_str), match_comma_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (reg_m[3].rm_so != -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "Comma remaining at: %d\n", reg_m[2].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+ have_comma_remaining = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ else {</span><br><span style="color: hsl(120, 100%, 40%);">+ have_comma_remaining = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fail_match = regexec(®exbuf_dash, ast_str_buffer(match_str), 3, reg_m, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fail_match) {</span><br><span style="color: hsl(120, 100%, 40%);">+ channel = atoi(ast_str_buffer(match_str));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (channel && (channel < DAHDI_MAX_SPANS)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_channels_search[channel] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "num: %d\n", channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ else {</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "process range: %s\n", ast_str_buffer(match_str));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ match_start = (ast_str_buffer(match_str) + reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+ match_len = (reg_m[1].rm_eo - reg_m[1].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+ *(ast_str_buffer(match_str) + match_len) = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_set(&match_str_from, 0, "%s", match_start);</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "range regex match: [%d:%d] %s (%d)\n", reg_m[1].rm_so, reg_m[1].rm_eo, ast_str_buffer(match_str_from), match_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ match_start = (ast_str_buffer(match_str) + reg_m[2].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+ match_len = (reg_m[2].rm_eo - reg_m[2].rm_so);</span><br><span style="color: hsl(120, 100%, 40%);">+// *(ast_str_buffer(match_str) + match_len) = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_set(&match_str_to, 0, "%s", match_start);</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "range regex match: [%d:%d] %s (%d)\n", reg_m[2].rm_so, reg_m[2].rm_eo, ast_str_buffer(match_str_to), match_len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ channel = atoi(ast_str_buffer(match_str_from));</span><br><span style="color: hsl(120, 100%, 40%);">+ channel_to = atoi(ast_str_buffer(match_str_to));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "range: %d->%d\n", channel, channel_to);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (channel && channel_to && (channel < DAHDI_MAX_SPANS) && (channel_to < DAHDI_MAX_SPANS)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = channel; i <= channel_to; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_channels_search[i] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* skip past the current match */</span><br><span style="color: hsl(120, 100%, 40%);">+ channel_arg_cur += match_comma_len;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* skip past the comma between matches */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (have_comma_remaining) {</span><br><span style="color: hsl(120, 100%, 40%);">+ channel_arg_cur++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ while (*channel_arg_cur);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// for (i = 0; i < DAHDI_MAX_SPANS; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+// if (dahdi_channels_search[i]) {</span><br><span style="color: hsl(120, 100%, 40%);">+// ast_log(LOG_NOTICE, "select -> %d\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+// }</span><br><span style="color: hsl(120, 100%, 40%);">+// }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_lock(&iflock);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {</span><br><span style="color: hsl(120, 100%, 40%);">+ channel = dahdi_chan->channel;</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((channel < 0) || !dahdi_channels_search[channel]) {</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Found the channel. Actually set it */</span><br><span style="color: hsl(120, 100%, 40%);">+ channels_touched++;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> Setting BusyOut Mode to: %s\n", channel, (on ? "On" : "Off"));</span><br><span style="color: hsl(120, 100%, 40%);">+ result = dahdi_set_channel_busyout(dahdi_chan, on);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (touched_channels) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* -1 (failure), 0 (no change), 1 (set), or 2 (queued) */</span><br><span style="color: hsl(120, 100%, 40%);">+ touched_channels[channel] = result;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_unlock(&iflock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ regfree(®exbuf_comma);</span><br><span style="color: hsl(120, 100%, 40%);">+ regfree(®exbuf_dash);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(channel_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return channels_touched;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Set the BusyOut mode on a specific dahdi channel</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param on Value of 0 for Disable, 1 for Enable</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 on no change</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 1 on change</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 2 on queue of operation</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int dahdi_set_channel_busyout(struct dahdi_pvt *dahdi_chan, int on)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int result = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (on) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_chan->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> BusyOut already enabled\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_chan->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pthread_t busyout_trying_threadid;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_chan->busyout_queued) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Channel DAHDI/%d already has a busyout queued\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_NOTICE, "Channel DAHDI/%d already has a call, queueing busyout\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busyout_queued = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ result = ast_pthread_create_detached(&busyout_trying_threadid, NULL, dahdi_set_channel_busyout_on_thread, dahdi_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (result) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Unable to start busyout queue thread on channel DAHDI/%d\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 2;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_lock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_busyout_start(dahdi_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* off */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_chan->busyout_queued) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busyout_queued = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Channel DAHDI/%d busyout queue cancelled\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dahdi_chan->busyout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> BusyOut already disabled\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_lock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busyout_queued = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busydetect = dahdi_chan->_busydetect;</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_chan->busyout = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/%d/busyout", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dahdi_chan->owner) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_hangup(dahdi_chan->owner);</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_set_hook(dahdi_chan->subs[SUB_REAL].dfd, DAHDI_ONHOOK);</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_fake_event(dahdi_chan, HANGUP);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Clear pending Ring/Answered from our busyout call */</span><br><span style="color: hsl(120, 100%, 40%);">+ dahdi_get_event(dahdi_chan->subs[SUB_REAL].dfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_unlock(&dahdi_chan->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_verb(1, "<DAHDI/%d> Disabled BusyOut\n", dahdi_chan->channel);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static int reload(void)</span><br><span> {</span><br><span>diff --git a/channels/chan_dahdi.h b/channels/chan_dahdi.h</span><br><span>index de813f2..13db791 100644</span><br><span>--- a/channels/chan_dahdi.h</span><br><span>+++ b/channels/chan_dahdi.h</span><br><span>@@ -203,6 +203,21 @@</span><br><span> * \note Set from the "busydetect" value read in from chan_dahdi.conf</span><br><span> */</span><br><span> unsigned int busydetect:1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief TRUE if busyout mode is enabled as per configured (backup of busydetect setting for when in busyout mode).</span><br><span style="color: hsl(120, 100%, 40%);">+ * (Listens for the beep-beep busy pattern.)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note Set from the "busydetect" value read in from chan_dahdi.conf</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int _busydetect:1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief TRUE if busyout mode is enabled.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int busyout:1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief TRUE if busyout mode is queued for enable.</span><br><span style="color: hsl(120, 100%, 40%);">+ * (If we have a call in progress, we will keep trying to enable busyout until the call is done)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int busyout_queued:1;</span><br><span> /*!</span><br><span> * \brief TRUE if call return is enabled.</span><br><span> * (*69, if your dialplan doesn't catch this first)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19264">change 19264</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/19264"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ib75c87c554bb18b8f65be73b4474474e7e1877b7 </div>
<div style="display:none"> Gerrit-Change-Number: 19264 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Mark Murawski <markm@intellasoft.net> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>