Asterisk - The Open Source Telephony Project  21.4.1
app_sla.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2022, Naveen Albert
5  *
6  * Based on previous MeetMe-based SLA Implementation by:
7  * Russell Bryant <russell@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19 
20 /*! \file
21  *
22  * \brief Shared Line Appearances
23  *
24  * \author Naveen Albert <asterisk@phreaknet.org>
25  *
26  * \ingroup applications
27  */
28 
29 /*! \li \ref app_sla.c uses configuration file \ref sla.conf
30  * \addtogroup configuration_file Configuration Files
31  */
32 
33 /*!
34  * \page sla.conf sla.conf
35  * \verbinclude sla.conf.sample
36  */
37 
38 /*** MODULEINFO
39  <depend>app_confbridge</depend>
40  <support_level>extended</support_level>
41  ***/
42 
43 #include "asterisk.h"
44 
45 #include "asterisk/lock.h"
46 #include "asterisk/file.h"
47 #include "asterisk/channel.h"
48 #include "asterisk/pbx.h"
49 #include "asterisk/module.h"
50 #include "asterisk/config.h"
51 #include "asterisk/app.h"
52 #include "asterisk/cli.h"
53 #include "asterisk/utils.h"
54 #include "asterisk/astobj2.h"
55 #include "asterisk/devicestate.h"
56 #include "asterisk/dial.h"
57 #include "asterisk/causes.h"
59 
60 /*** DOCUMENTATION
61  <application name="SLAStation" language="en_US">
62  <synopsis>
63  Shared Line Appearance Station.
64  </synopsis>
65  <syntax>
66  <parameter name="station" required="true">
67  <para>Station name</para>
68  </parameter>
69  </syntax>
70  <description>
71  <para>This application should be executed by an SLA station. The argument depends
72  on how the call was initiated. If the phone was just taken off hook, then the argument
73  <replaceable>station</replaceable> should be just the station name. If the call was
74  initiated by pressing a line key, then the station name should be preceded by an underscore
75  and the trunk name associated with that line button.</para>
76  <para>For example: <literal>station1_line1</literal></para>
77  <para>On exit, this application will set the variable <variable>SLASTATION_STATUS</variable> to
78  one of the following values:</para>
79  <variablelist>
80  <variable name="SLASTATION_STATUS">
81  <value name="FAILURE" />
82  <value name="CONGESTION" />
83  <value name="SUCCESS" />
84  </variable>
85  </variablelist>
86  </description>
87  </application>
88  <application name="SLATrunk" language="en_US">
89  <synopsis>
90  Shared Line Appearance Trunk.
91  </synopsis>
92  <syntax>
93  <parameter name="trunk" required="true">
94  <para>Trunk name</para>
95  </parameter>
96  <parameter name="options">
97  <optionlist>
98  <option name="M" hasparams="optional">
99  <para>Play back the specified MOH <replaceable>class</replaceable>
100  instead of ringing</para>
101  <argument name="class" required="true" />
102  </option>
103  </optionlist>
104  </parameter>
105  </syntax>
106  <description>
107  <para>This application should be executed by an SLA trunk on an inbound call. The channel calling
108  this application should correspond to the SLA trunk with the name <replaceable>trunk</replaceable>
109  that is being passed as an argument.</para>
110  <para>On exit, this application will set the variable <variable>SLATRUNK_STATUS</variable> to
111  one of the following values:</para>
112  <variablelist>
113  <variable name="SLATRUNK_STATUS">
114  <value name="FAILURE" />
115  <value name="SUCCESS" />
116  <value name="UNANSWERED" />
117  <value name="RINGTIMEOUT" />
118  </variable>
119  </variablelist>
120  </description>
121  </application>
122  ***/
123 
124 #define SLA_CONFIG_FILE "sla.conf"
125 #define MAX_CONFNUM 80
126 
127 static const char * const slastation_app = "SLAStation";
128 static const char * const slatrunk_app = "SLATrunk";
129 
130 enum {
131  /*! If set there will be no enter or leave sounds */
132  CONFFLAG_QUIET = (1 << 0),
133  /*! Set to have music on hold when user is alone in conference */
134  CONFFLAG_MOH = (1 << 1),
135  /*! If set, the channel will leave the conference if all marked users leave */
137  /*! If set, the user will be marked */
139  /*! Pass DTMF through the conference */
140  CONFFLAG_PASS_DTMF = (1 << 4),
141  CONFFLAG_SLA_STATION = (1 << 5),
142  CONFFLAG_SLA_TRUNK = (1 << 6),
143 };
144 
145 enum {
146  SLA_TRUNK_OPT_MOH = (1 << 0),
147 };
148 
149 enum {
150  SLA_TRUNK_OPT_ARG_MOH_CLASS = 0,
151  SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1,
152 };
153 
154 AST_APP_OPTIONS(sla_trunk_opts, BEGIN_OPTIONS
155  AST_APP_OPTION_ARG('M', SLA_TRUNK_OPT_MOH, SLA_TRUNK_OPT_ARG_MOH_CLASS),
156 END_OPTIONS );
157 
158 enum sla_which_trunk_refs {
159  ALL_TRUNK_REFS,
160  INACTIVE_TRUNK_REFS,
161 };
162 
163 enum sla_trunk_state {
164  SLA_TRUNK_STATE_IDLE,
165  SLA_TRUNK_STATE_RINGING,
166  SLA_TRUNK_STATE_UP,
167  SLA_TRUNK_STATE_ONHOLD,
168  SLA_TRUNK_STATE_ONHOLD_BYME,
169 };
170 
172  /*! This means that any station can put it on hold, and any station
173  * can retrieve the call from hold. */
175  /*! This means that only the station that put the call on hold may
176  * retrieve it from hold. */
178 };
179 
180 struct sla_trunk_ref;
181 
182 struct sla_station {
183  AST_RWLIST_ENTRY(sla_station) entry;
185  AST_STRING_FIELD(name);
186  AST_STRING_FIELD(device);
187  AST_STRING_FIELD(autocontext);
188  );
190  struct ast_dial *dial;
191  /*! Ring timeout for this station, for any trunk. If a ring timeout
192  * is set for a specific trunk on this station, that will take
193  * priority over this value. */
194  unsigned int ring_timeout;
195  /*! Ring delay for this station, for any trunk. If a ring delay
196  * is set for a specific trunk on this station, that will take
197  * priority over this value. */
198  unsigned int ring_delay;
199  /*! This option uses the values in the sla_hold_access enum and sets the
200  * access control type for hold on this station. */
201  unsigned int hold_access:1;
202  /*! Mark used during reload processing */
203  unsigned int mark:1;
204 };
205 
206 /*!
207  * \brief A reference to a station
208  *
209  * This struct looks near useless at first glance. However, its existence
210  * in the list of stations in sla_trunk means that this station references
211  * that trunk. We use the mark to keep track of whether it needs to be
212  * removed from the sla_trunk's list of stations during a reload.
213  */
216  struct sla_station *station;
217  /*! Mark used during reload processing */
218  unsigned int mark:1;
219 };
220 
221 struct sla_trunk {
223  AST_STRING_FIELD(name);
224  AST_STRING_FIELD(device);
225  AST_STRING_FIELD(autocontext);
226  );
228  /*! Number of stations that use this trunk */
229  unsigned int num_stations;
230  /*! Number of stations currently on a call with this trunk */
231  unsigned int active_stations;
232  /*! Number of stations that have this trunk on hold. */
233  unsigned int hold_stations;
234  struct ast_channel *chan;
235  unsigned int ring_timeout;
236  /*! If set to 1, no station will be able to join an active call with
237  * this trunk. */
238  unsigned int barge_disabled:1;
239  /*! This option uses the values in the sla_hold_access enum and sets the
240  * access control type for hold on this trunk. */
241  unsigned int hold_access:1;
242  /*! Whether this trunk is currently on hold, meaning that once a station
243  * connects to it, the trunk channel needs to have UNHOLD indicated to it. */
244  unsigned int on_hold:1;
245  /*! Mark used during reload processing */
246  unsigned int mark:1;
247 };
248 
249 /*!
250  * \brief A station's reference to a trunk
251  *
252  * An sla_station keeps a list of trunk_refs. This holds metadata about the
253  * stations usage of the trunk.
254  */
257  struct sla_trunk *trunk;
258  enum sla_trunk_state state;
259  struct ast_channel *chan;
260  /*! Ring timeout to use when this trunk is ringing on this specific
261  * station. This takes higher priority than a ring timeout set at
262  * the station level. */
263  unsigned int ring_timeout;
264  /*! Ring delay to use when this trunk is ringing on this specific
265  * station. This takes higher priority than a ring delay set at
266  * the station level. */
267  unsigned int ring_delay;
268  /*! Mark used during reload processing */
269  unsigned int mark:1;
270 };
271 
272 static struct ao2_container *sla_stations;
273 static struct ao2_container *sla_trunks;
274 
275 static const char sla_registrar[] = "SLA";
276 
277 /*! \brief Event types that can be queued up for the SLA thread */
279  /*! A station has put the call on hold */
281  /*! The state of a dial has changed */
283  /*! The state of a ringing trunk has changed */
285 };
286 
287 struct sla_event {
288  enum sla_event_type type;
289  struct sla_station *station;
290  struct sla_trunk_ref *trunk_ref;
292 };
293 
294 /*! \brief A station that failed to be dialed
295  * \note Only used by the SLA thread. */
297  struct sla_station *station;
298  struct timeval last_try;
300 };
301 
302 /*! \brief A trunk that is ringing */
304  struct sla_trunk *trunk;
305  /*! The time that this trunk started ringing */
306  struct timeval ring_begin;
307  AST_LIST_HEAD_NOLOCK(, sla_station_ref) timed_out_stations;
309 };
310 
311 enum sla_station_hangup {
312  SLA_STATION_HANGUP_NORMAL,
313  SLA_STATION_HANGUP_TIMEOUT,
314 };
315 
316 /*! \brief A station that is ringing */
318  struct sla_station *station;
319  /*! The time that this station started ringing */
320  struct timeval ring_begin;
322 };
323 
324 /*!
325  * \brief A structure for data used by the sla thread
326  */
327 static struct {
328  /*! The SLA thread ID */
329  pthread_t thread;
330  ast_cond_t cond;
332  AST_LIST_HEAD_NOLOCK(, sla_ringing_trunk) ringing_trunks;
333  AST_LIST_HEAD_NOLOCK(, sla_ringing_station) ringing_stations;
334  AST_LIST_HEAD_NOLOCK(, sla_failed_station) failed_stations;
335  AST_LIST_HEAD_NOLOCK(, sla_event) event_q;
336  unsigned int stop:1;
337  /*! Attempt to handle CallerID, even though it is known not to work
338  * properly in some situations. */
339  unsigned int attempt_callerid:1;
340 } sla = {
341  .thread = AST_PTHREADT_NULL,
342 };
343 
344 static const char *sla_hold_str(unsigned int hold_access)
345 {
346  const char *hold = "Unknown";
347 
348  switch (hold_access) {
349  case SLA_HOLD_OPEN:
350  hold = "Open";
351  break;
352  case SLA_HOLD_PRIVATE:
353  hold = "Private";
354  default:
355  break;
356  }
357 
358  return hold;
359 }
360 
361 static char *sla_show_trunks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
362 {
363  struct ao2_iterator i;
364  struct sla_trunk *trunk;
365 
366  switch (cmd) {
367  case CLI_INIT:
368  e->command = "sla show trunks";
369  e->usage =
370  "Usage: sla show trunks\n"
371  " This will list all trunks defined in sla.conf\n";
372  return NULL;
373  case CLI_GENERATE:
374  return NULL;
375  }
376 
377  ast_cli(a->fd, "\n"
378  "=============================================================\n"
379  "=== Configured SLA Trunks ===================================\n"
380  "=============================================================\n"
381  "===\n");
382  i = ao2_iterator_init(sla_trunks, 0);
383  for (; (trunk = ao2_iterator_next(&i)); ao2_ref(trunk, -1)) {
384  struct sla_station_ref *station_ref;
385  char ring_timeout[23] = "(none)";
386 
387  ao2_lock(trunk);
388 
389  if (trunk->ring_timeout) {
390  snprintf(ring_timeout, sizeof(ring_timeout), "%u Seconds", trunk->ring_timeout);
391  }
392 
393  ast_cli(a->fd, "=== ---------------------------------------------------------\n"
394  "=== Trunk Name: %s\n"
395  "=== ==> Device: %s\n"
396  "=== ==> AutoContext: %s\n"
397  "=== ==> RingTimeout: %s\n"
398  "=== ==> BargeAllowed: %s\n"
399  "=== ==> HoldAccess: %s\n"
400  "=== ==> Stations ...\n",
401  trunk->name, trunk->device,
402  S_OR(trunk->autocontext, "(none)"),
403  ring_timeout,
404  trunk->barge_disabled ? "No" : "Yes",
405  sla_hold_str(trunk->hold_access));
406 
407  AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
408  ast_cli(a->fd, "=== ==> Station name: %s\n", station_ref->station->name);
409  }
410 
411  ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
412 
413  ao2_unlock(trunk);
414  }
416  ast_cli(a->fd, "=============================================================\n\n");
417 
418  return CLI_SUCCESS;
419 }
420 
421 static const char *trunkstate2str(enum sla_trunk_state state)
422 {
423 #define S(e) case e: return # e;
424  switch (state) {
425  S(SLA_TRUNK_STATE_IDLE)
426  S(SLA_TRUNK_STATE_RINGING)
427  S(SLA_TRUNK_STATE_UP)
428  S(SLA_TRUNK_STATE_ONHOLD)
429  S(SLA_TRUNK_STATE_ONHOLD_BYME)
430  }
431  return "Uknown State";
432 #undef S
433 }
434 
435 static char *sla_show_stations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
436 {
437  struct ao2_iterator i;
438  struct sla_station *station;
439 
440  switch (cmd) {
441  case CLI_INIT:
442  e->command = "sla show stations";
443  e->usage =
444  "Usage: sla show stations\n"
445  " This will list all stations defined in sla.conf\n";
446  return NULL;
447  case CLI_GENERATE:
448  return NULL;
449  }
450 
451  ast_cli(a->fd, "\n"
452  "=============================================================\n"
453  "=== Configured SLA Stations =================================\n"
454  "=============================================================\n"
455  "===\n");
456  i = ao2_iterator_init(sla_stations, 0);
457  for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
458  struct sla_trunk_ref *trunk_ref;
459  char ring_timeout[16] = "(none)";
460  char ring_delay[16] = "(none)";
461 
462  ao2_lock(station);
463 
464  if (station->ring_timeout) {
465  snprintf(ring_timeout, sizeof(ring_timeout), "%u", station->ring_timeout);
466  }
467  if (station->ring_delay) {
468  snprintf(ring_delay, sizeof(ring_delay), "%u", station->ring_delay);
469  }
470  ast_cli(a->fd, "=== ---------------------------------------------------------\n"
471  "=== Station Name: %s\n"
472  "=== ==> Device: %s\n"
473  "=== ==> AutoContext: %s\n"
474  "=== ==> RingTimeout: %s\n"
475  "=== ==> RingDelay: %s\n"
476  "=== ==> HoldAccess: %s\n"
477  "=== ==> Trunks ...\n",
478  station->name, station->device,
479  S_OR(station->autocontext, "(none)"),
480  ring_timeout, ring_delay,
481  sla_hold_str(station->hold_access));
482  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
483  if (trunk_ref->ring_timeout) {
484  snprintf(ring_timeout, sizeof(ring_timeout), "%u", trunk_ref->ring_timeout);
485  } else {
486  strcpy(ring_timeout, "(none)");
487  }
488  if (trunk_ref->ring_delay) {
489  snprintf(ring_delay, sizeof(ring_delay), "%u", trunk_ref->ring_delay);
490  } else {
491  strcpy(ring_delay, "(none)");
492  }
493 
494  ast_cli(a->fd, "=== ==> Trunk Name: %s\n"
495  "=== ==> State: %s\n"
496  "=== ==> RingTimeout: %s\n"
497  "=== ==> RingDelay: %s\n",
498  trunk_ref->trunk->name,
499  trunkstate2str(trunk_ref->state),
500  ring_timeout, ring_delay);
501  }
502  ast_cli(a->fd, "=== ---------------------------------------------------------\n"
503  "===\n");
504 
505  ao2_unlock(station);
506  }
508  ast_cli(a->fd, "============================================================\n"
509  "\n");
510 
511  return CLI_SUCCESS;
512 }
513 
514 static struct ast_cli_entry cli_sla[] = {
515  AST_CLI_DEFINE(sla_show_trunks, "Show SLA Trunks"),
516  AST_CLI_DEFINE(sla_show_stations, "Show SLA Stations"),
517 };
518 
519 static void sla_queue_event_full(enum sla_event_type type, struct sla_trunk_ref *trunk_ref, struct sla_station *station, int lock)
520 {
521  struct sla_event *event;
522 
523  if (sla.thread == AST_PTHREADT_NULL) {
524  ao2_ref(station, -1);
525  ao2_ref(trunk_ref, -1);
526  return;
527  }
528 
529  if (!(event = ast_calloc(1, sizeof(*event)))) {
530  ao2_ref(station, -1);
531  ao2_ref(trunk_ref, -1);
532  return;
533  }
534 
535  event->type = type;
536  event->trunk_ref = trunk_ref;
537  event->station = station;
538 
539  if (!lock) {
540  AST_LIST_INSERT_TAIL(&sla.event_q, event, entry);
541  return;
542  }
543 
544  ast_mutex_lock(&sla.lock);
545  AST_LIST_INSERT_TAIL(&sla.event_q, event, entry);
546  ast_cond_signal(&sla.cond);
547  ast_mutex_unlock(&sla.lock);
548 }
549 
550 static void sla_queue_event_nolock(enum sla_event_type type)
551 {
552  sla_queue_event_full(type, NULL, NULL, 0);
553 }
554 
555 static void sla_queue_event(enum sla_event_type type)
556 {
557  sla_queue_event_full(type, NULL, NULL, 1);
558 }
559 
560 /*! \brief Queue a SLA event from the conference */
561 static void sla_queue_event_conf(enum sla_event_type type, struct ast_channel *chan, const char *confname)
562 {
563  struct sla_station *station;
564  struct sla_trunk_ref *trunk_ref = NULL;
565  char *trunk_name;
566  struct ao2_iterator i;
567 
568  trunk_name = ast_strdupa(confname);
569  strsep(&trunk_name, "_");
570  if (ast_strlen_zero(trunk_name)) {
571  ast_log(LOG_ERROR, "Invalid conference name for SLA - '%s'!\n", confname);
572  return;
573  }
574 
575  i = ao2_iterator_init(sla_stations, 0);
576  while ((station = ao2_iterator_next(&i))) {
577  ao2_lock(station);
578  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
579  if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) {
580  ao2_ref(trunk_ref, 1);
581  break;
582  }
583  }
584  ao2_unlock(station);
585  if (trunk_ref) {
586  /* station reference given to sla_queue_event_full() */
587  break;
588  }
589  ao2_ref(station, -1);
590  }
592 
593  if (!trunk_ref) {
594  ast_debug(1, "Trunk not found for event!\n");
595  return;
596  }
597 
598  sla_queue_event_full(type, trunk_ref, station, 1);
599 }
600 
601 /*!
602  * \brief Framehook to support HOLD within the conference
603  */
604 
606  int framehook_id;
607  char *confname;
608 };
609 
610 static const struct ast_datastore_info sla_framehook_datastore = {
611  .type = "app_sla",
612 };
613 
614 static int remove_framehook(struct ast_channel *chan)
615 {
616  struct ast_datastore *datastore = NULL;
617  struct sla_framehook_data *data;
618  SCOPED_CHANNELLOCK(chan_lock, chan);
619 
620  datastore = ast_channel_datastore_find(chan, &sla_framehook_datastore, NULL);
621  if (!datastore) {
622  ast_log(AST_LOG_WARNING, "Cannot remove framehook from %s: HOLD_INTERCEPT not currently enabled\n", ast_channel_name(chan));
623  return -1;
624  }
625  data = datastore->data;
626 
627  ast_free(data->confname);
628 
629  if (ast_framehook_detach(chan, data->framehook_id)) {
630  ast_log(AST_LOG_WARNING, "Failed to remove framehook from channel %s\n", ast_channel_name(chan));
631  return -1;
632  }
633  if (ast_channel_datastore_remove(chan, datastore)) {
634  ast_log(AST_LOG_WARNING, "Failed to remove datastore from channel %s\n", ast_channel_name(chan));
635  return -1;
636  }
637  ast_datastore_free(datastore);
638 
639  return 0;
640 }
641 
642 static struct ast_frame *sla_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
643 {
644  struct sla_framehook_data *sla_data = data;
645  if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
646  return f;
647  }
649  sla_queue_event_conf(SLA_EVENT_HOLD, chan, sla_data->confname);
650  }
651  return f;
652 }
653 
654 /*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
655 static int sla_framehook_consume(void *data, enum ast_frame_type type)
656 {
657  return (type == AST_FRAME_CONTROL ? 1 : 0);
658 }
659 
660 static int attach_framehook(struct ast_channel *chan, const char *confname)
661 {
662  struct ast_datastore *datastore;
663  struct sla_framehook_data *data;
664  static struct ast_framehook_interface sla_framehook_interface = {
665  .version = AST_FRAMEHOOK_INTERFACE_VERSION,
666  .event_cb = sla_framehook,
667  .consume_cb = sla_framehook_consume,
668  .disable_inheritance = 1,
669  };
670  SCOPED_CHANNELLOCK(chan_lock, chan);
671 
672  datastore = ast_channel_datastore_find(chan, &sla_framehook_datastore, NULL);
673  if (datastore) {
674  ast_log(AST_LOG_WARNING, "SLA framehook already set on '%s'\n", ast_channel_name(chan));
675  return 0;
676  }
677 
678  datastore = ast_datastore_alloc(&sla_framehook_datastore, NULL);
679  if (!datastore) {
680  return -1;
681  }
682 
683  data = ast_calloc(1, sizeof(*data));
684  if (!data) {
685  ast_datastore_free(datastore);
686  return -1;
687  }
688 
689  data->framehook_id = ast_framehook_attach(chan, &sla_framehook_interface);
690  data->confname = ast_strdup(confname);
691  if (!data->confname || data->framehook_id < 0) {
692  ast_log(AST_LOG_WARNING, "Failed to attach SLA framehook to '%s'\n", ast_channel_name(chan));
693  ast_datastore_free(datastore);
694  ast_free(data);
695  return -1;
696  }
697  datastore->data = data;
698 
699  ast_channel_datastore_add(chan, datastore);
700  return 0;
701 }
702 
703 /*!
704  * \internal
705  * \brief Find an SLA trunk by name
706  */
707 static struct sla_trunk *sla_find_trunk(const char *name)
708 {
709  struct sla_trunk tmp_trunk = {
710  .name = name,
711  };
712 
713  return ao2_find(sla_trunks, &tmp_trunk, OBJ_POINTER);
714 }
715 
716 /*!
717  * \internal
718  * \brief Find an SLA station by name
719  */
720 static struct sla_station *sla_find_station(const char *name)
721 {
722  struct sla_station tmp_station = {
723  .name = name,
724  };
725 
726  return ao2_find(sla_stations, &tmp_station, OBJ_POINTER);
727 }
728 
729 static int sla_check_station_hold_access(const struct sla_trunk *trunk, const struct sla_station *station)
730 {
731  struct sla_station_ref *station_ref;
732  struct sla_trunk_ref *trunk_ref;
733 
734  /* For each station that has this call on hold, check for private hold. */
735  AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
736  AST_LIST_TRAVERSE(&station_ref->station->trunks, trunk_ref, entry) {
737  if (trunk_ref->trunk != trunk || station_ref->station == station) {
738  continue;
739  }
740  if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME && station_ref->station->hold_access == SLA_HOLD_PRIVATE) {
741  return 1;
742  }
743  return 0;
744  }
745  }
746 
747  return 0;
748 }
749 
750 /*!
751  * \brief Find a trunk reference on a station by name
752  * \param station the station
753  * \param name the trunk's name
754  * \pre sla_station is locked
755  * \return a pointer to the station's trunk reference. If the trunk
756  * is not found, it is not idle and barge is disabled, or if
757  * it is on hold and private hold is set, then NULL will be returned.
758  */
759 static struct sla_trunk_ref *sla_find_trunk_ref_byname(const struct sla_station *station, const char *name)
760 {
761  struct sla_trunk_ref *trunk_ref = NULL;
762 
763  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
764  if (strcasecmp(trunk_ref->trunk->name, name)) {
765  continue;
766  }
767 
768  if (trunk_ref->trunk->barge_disabled && trunk_ref->state == SLA_TRUNK_STATE_UP) {
769  ast_debug(2, "Barge disabled, trunk not available\n");
770  trunk_ref = NULL;
771  } else if (trunk_ref->trunk->hold_stations && trunk_ref->trunk->hold_access == SLA_HOLD_PRIVATE && trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
772  ast_debug(2, "Private hold by another station\n");
773  trunk_ref = NULL;
774  } else if (sla_check_station_hold_access(trunk_ref->trunk, station)) {
775  ast_debug(2, "No hold access\n");
776  trunk_ref = NULL;
777  }
778 
779  break;
780  }
781 
782  if (trunk_ref) {
783  ao2_ref(trunk_ref, 1);
784  }
785 
786  return trunk_ref;
787 }
788 
789 static void sla_station_ref_destructor(void *obj)
790 {
791  struct sla_station_ref *station_ref = obj;
792 
793  if (station_ref->station) {
794  ao2_ref(station_ref->station, -1);
795  station_ref->station = NULL;
796  }
797 }
798 
799 static struct sla_station_ref *sla_create_station_ref(struct sla_station *station)
800 {
801  struct sla_station_ref *station_ref;
802 
803  if (!(station_ref = ao2_alloc(sizeof(*station_ref), sla_station_ref_destructor))) {
804  return NULL;
805  }
806 
807  ao2_ref(station, 1);
808  station_ref->station = station;
809 
810  return station_ref;
811 }
812 
813 static struct sla_ringing_station *sla_create_ringing_station(struct sla_station *station)
814 {
815  struct sla_ringing_station *ringing_station;
816 
817  if (!(ringing_station = ast_calloc(1, sizeof(*ringing_station)))) {
818  return NULL;
819  }
820 
821  ao2_ref(station, 1);
822  ringing_station->station = station;
823  ringing_station->ring_begin = ast_tvnow();
824 
825  return ringing_station;
826 }
827 
828 static void sla_ringing_station_destroy(struct sla_ringing_station *ringing_station)
829 {
830  if (ringing_station->station) {
831  ao2_ref(ringing_station->station, -1);
832  ringing_station->station = NULL;
833  }
834 
835  ast_free(ringing_station);
836 }
837 
838 static struct sla_failed_station *sla_create_failed_station(struct sla_station *station)
839 {
840  struct sla_failed_station *failed_station;
841 
842  if (!(failed_station = ast_calloc(1, sizeof(*failed_station)))) {
843  return NULL;
844  }
845 
846  ao2_ref(station, 1);
847  failed_station->station = station;
848  failed_station->last_try = ast_tvnow();
849 
850  return failed_station;
851 }
852 
853 static void sla_failed_station_destroy(struct sla_failed_station *failed_station)
854 {
855  if (failed_station->station) {
856  ao2_ref(failed_station->station, -1);
857  failed_station->station = NULL;
858  }
859 
860  ast_free(failed_station);
861 }
862 
863 static enum ast_device_state sla_state_to_devstate(enum sla_trunk_state state)
864 {
865  switch (state) {
866  case SLA_TRUNK_STATE_IDLE:
867  return AST_DEVICE_NOT_INUSE;
868  case SLA_TRUNK_STATE_RINGING:
869  return AST_DEVICE_RINGING;
870  case SLA_TRUNK_STATE_UP:
871  return AST_DEVICE_INUSE;
872  case SLA_TRUNK_STATE_ONHOLD:
873  case SLA_TRUNK_STATE_ONHOLD_BYME:
874  return AST_DEVICE_ONHOLD;
875  }
876 
877  return AST_DEVICE_UNKNOWN;
878 }
879 
880 static void sla_change_trunk_state(const struct sla_trunk *trunk, enum sla_trunk_state state,
881  enum sla_which_trunk_refs inactive_only, const struct sla_trunk_ref *exclude)
882 {
883  struct sla_station *station;
884  struct sla_trunk_ref *trunk_ref;
885  struct ao2_iterator i;
886 
887  i = ao2_iterator_init(sla_stations, 0);
888  while ((station = ao2_iterator_next(&i))) {
889  ao2_lock(station);
890  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
891  if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) || trunk_ref == exclude) {
892  continue;
893  }
894  trunk_ref->state = state;
895  ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE, "SLA:%s_%s", station->name, trunk->name);
896  break;
897  }
898  ao2_unlock(station);
899  ao2_ref(station, -1);
900  }
902 }
903 
905  struct sla_station *station;
906  struct sla_trunk_ref *trunk_ref;
907  ast_mutex_t *cond_lock;
908  ast_cond_t *cond;
909 };
910 
911 static void answer_trunk_chan(struct ast_channel *chan)
912 {
913  ast_raw_answer(chan); /* Do NOT use ast_answer since that waits for media using ast_waitfor_nandfds. */
914  ast_indicate(chan, -1);
915 }
916 
917 static int conf_run(struct ast_channel *chan, const char *confname, struct ast_flags *confflags, char *optargs[])
918 {
919  char confbridge_args[256];
920  int res = 0;
921 
922  snprintf(confbridge_args, sizeof(confbridge_args), "%s", confname);
923 
924  res |= ast_func_write(chan, "CONFBRIDGE(user,quiet)", ast_test_flag(confflags, CONFFLAG_QUIET) ? "1" : "0");
925  res |= ast_func_write(chan, "CONFBRIDGE(user,dtmf_passthrough)", ast_test_flag(confflags, CONFFLAG_PASS_DTMF) ? "1" : "0");
926  res |= ast_func_write(chan, "CONFBRIDGE(user,marked)", ast_test_flag(confflags, CONFFLAG_MARKEDUSER) ? "1" : "0");
927  res |= ast_func_write(chan, "CONFBRIDGE(user,end_marked)", ast_test_flag(confflags, CONFFLAG_MARKEDEXIT) ? "1" : "0");
928  res |= ast_func_write(chan, "CONFBRIDGE(user,music_on_hold_when_empty)", ast_test_flag(confflags, CONFFLAG_MOH) ? "1" : "0");
929  if (ast_test_flag(confflags, CONFFLAG_MOH) && !ast_strlen_zero(optargs[SLA_TRUNK_OPT_ARG_MOH_CLASS])) {
930  res |= ast_func_write(chan, "CONFBRIDGE(user,music_on_hold_class)", optargs[SLA_TRUNK_OPT_ARG_MOH_CLASS]);
931  }
932 
933  if (res) {
934  ast_log(LOG_ERROR, "Failed to set up conference, aborting\n");
935  return -1;
936  }
937 
938  /* Attach a framehook that we'll use to process HOLD from stations. */
939  if (ast_test_flag(confflags, CONFFLAG_SLA_STATION) && attach_framehook(chan, confname)) {
940  return -1;
941  }
942 
943  ast_debug(2, "Channel %s is running ConfBridge(%s)\n", ast_channel_name(chan), confbridge_args);
944  res = ast_pbx_exec_application(chan, "ConfBridge", confbridge_args);
945 
946  if (ast_test_flag(confflags, CONFFLAG_SLA_STATION)) {
947  remove_framehook(chan);
948  }
949  return res;
950 }
951 
952 static int conf_kick_all(struct ast_channel *chan, const char *confname)
953 {
954  char confkick_args[256];
955 
956  snprintf(confkick_args, sizeof(confkick_args), "%s,all", confname);
957  ast_debug(2, "Kicking all participants from conference %s\n", confname);
958 
959  if (chan) {
960  return ast_pbx_exec_application(chan, "ConfKick", confkick_args);
961  } else {
962  /* We might not have a channel available to us, use a dummy channel in that case. */
963  chan = ast_dummy_channel_alloc();
964  if (!chan) {
965  ast_log(LOG_WARNING, "Failed to allocate dummy channel\n");
966  return -1;
967  } else {
968  int res = ast_pbx_exec_application(chan, "ConfKick", confkick_args);
969  ast_channel_unref(chan);
970  return res;
971  }
972  }
973 }
974 
975 static void *run_station(void *data)
976 {
977  RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
978  RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, ao2_cleanup);
979  struct ast_str *conf_name = ast_str_create(16);
980  struct ast_flags conf_flags = { 0 };
981 
982  {
983  struct run_station_args *args = data;
984  station = args->station;
985  trunk_ref = args->trunk_ref;
986  ast_mutex_lock(args->cond_lock);
987  ast_cond_signal(args->cond);
988  ast_mutex_unlock(args->cond_lock);
989  /* args is no longer valid here. */
990  }
991 
992  ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1);
993  ast_str_set(&conf_name, 0, "SLA_%s", trunk_ref->trunk->name);
994  ast_set_flag(&conf_flags, CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION);
995  answer_trunk_chan(trunk_ref->chan);
996 
997  ast_debug(2, "Station %s joining conference %s\n", station->name, ast_str_buffer(conf_name));
998  conf_run(trunk_ref->chan, ast_str_buffer(conf_name), &conf_flags, NULL);
999 
1000  trunk_ref->chan = NULL;
1001  if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) &&
1002  trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
1003  conf_kick_all(NULL, ast_str_buffer(conf_name));
1004  trunk_ref->trunk->hold_stations = 0;
1005  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
1006  }
1007 
1008  ast_dial_join(station->dial);
1009  ast_dial_destroy(station->dial);
1010  station->dial = NULL;
1011  ast_free(conf_name);
1012 
1013  return NULL;
1014 }
1015 
1016 static void sla_ringing_trunk_destroy(struct sla_ringing_trunk *ringing_trunk);
1017 
1018 static void sla_stop_ringing_trunk(struct sla_ringing_trunk *ringing_trunk)
1019 {
1020  struct sla_station_ref *station_ref;
1021 
1022  conf_kick_all(ringing_trunk->trunk->chan, ringing_trunk->trunk->name);
1023  sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
1024 
1025  while ((station_ref = AST_LIST_REMOVE_HEAD(&ringing_trunk->timed_out_stations, entry))) {
1026  ao2_ref(station_ref, -1);
1027  }
1028 
1029  sla_ringing_trunk_destroy(ringing_trunk);
1030 }
1031 
1032 static void sla_stop_ringing_station(struct sla_ringing_station *ringing_station, enum sla_station_hangup hangup)
1033 {
1034  struct sla_ringing_trunk *ringing_trunk;
1035  struct sla_trunk_ref *trunk_ref;
1036  struct sla_station_ref *station_ref;
1037 
1038  ast_dial_join(ringing_station->station->dial);
1039  ast_dial_destroy(ringing_station->station->dial);
1040  ringing_station->station->dial = NULL;
1041 
1042  if (hangup == SLA_STATION_HANGUP_NORMAL) {
1043  goto done;
1044  }
1045 
1046  /* If the station is being hung up because of a timeout, then add it to the
1047  * list of timed out stations on each of the ringing trunks. This is so
1048  * that when doing further processing to figure out which stations should be
1049  * ringing, which trunk to answer, determining timeouts, etc., we know which
1050  * ringing trunks we should ignore. */
1051  AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1052  AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) {
1053  if (ringing_trunk->trunk == trunk_ref->trunk) {
1054  break;
1055  }
1056  }
1057  if (!trunk_ref) {
1058  continue;
1059  }
1060  if (!(station_ref = sla_create_station_ref(ringing_station->station))) {
1061  continue;
1062  }
1063  AST_LIST_INSERT_TAIL(&ringing_trunk->timed_out_stations, station_ref, entry);
1064  }
1065 
1066 done:
1067  sla_ringing_station_destroy(ringing_station);
1068 }
1069 
1070 static void sla_dial_state_callback(struct ast_dial *dial)
1071 {
1072  sla_queue_event(SLA_EVENT_DIAL_STATE);
1073 }
1074 
1075 /*! \brief Check to see if dialing this station already timed out for this ringing trunk
1076  * \note Assumes sla.lock is locked
1077  */
1078 static int sla_check_timed_out_station(const struct sla_ringing_trunk *ringing_trunk, const struct sla_station *station)
1079 {
1080  struct sla_station_ref *timed_out_station;
1081 
1082  AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) {
1083  if (station == timed_out_station->station) {
1084  return 1;
1085  }
1086  }
1087 
1088  return 0;
1089 }
1090 
1091 /*! \brief Choose the highest priority ringing trunk for a station
1092  * \param station the station
1093  * \param rm remove the ringing trunk once selected
1094  * \param trunk_ref a place to store the pointer to this stations reference to
1095  * the selected trunk
1096  * \return a pointer to the selected ringing trunk, or NULL if none found
1097  * \note Assumes that sla.lock is locked
1098  */
1099 static struct sla_ringing_trunk *sla_choose_ringing_trunk(struct sla_station *station, struct sla_trunk_ref **trunk_ref, int rm)
1100 {
1101  struct sla_trunk_ref *s_trunk_ref;
1102  struct sla_ringing_trunk *ringing_trunk = NULL;
1103 
1104  AST_LIST_TRAVERSE(&station->trunks, s_trunk_ref, entry) {
1105  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
1106  /* Make sure this is the trunk we're looking for */
1107  if (s_trunk_ref->trunk != ringing_trunk->trunk) {
1108  continue;
1109  }
1110 
1111  /* This trunk on the station is ringing. But, make sure this station
1112  * didn't already time out while this trunk was ringing. */
1113  if (sla_check_timed_out_station(ringing_trunk, station)) {
1114  continue;
1115  }
1116 
1117  if (rm) {
1118  AST_LIST_REMOVE_CURRENT(entry);
1119  }
1120 
1121  if (trunk_ref) {
1122  ao2_ref(s_trunk_ref, 1);
1123  *trunk_ref = s_trunk_ref;
1124  }
1125 
1126  break;
1127  }
1129 
1130  if (ringing_trunk) {
1131  break;
1132  }
1133  }
1134 
1135  return ringing_trunk;
1136 }
1137 
1138 static void sla_handle_dial_state_event(void)
1139 {
1140  struct sla_ringing_station *ringing_station;
1141 
1142  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
1143  RAII_VAR(struct sla_trunk_ref *, s_trunk_ref, NULL, ao2_cleanup);
1144  struct sla_ringing_trunk *ringing_trunk = NULL;
1145  struct run_station_args args;
1146  enum ast_dial_result dial_res;
1147  pthread_t dont_care;
1148  ast_mutex_t cond_lock;
1149  ast_cond_t cond;
1150 
1151  switch ((dial_res = ast_dial_state(ringing_station->station->dial))) {
1157  AST_LIST_REMOVE_CURRENT(entry);
1158  sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL);
1159  break;
1161  AST_LIST_REMOVE_CURRENT(entry);
1162  /* Find the appropriate trunk to answer. */
1163  ast_mutex_lock(&sla.lock);
1164  ringing_trunk = sla_choose_ringing_trunk(ringing_station->station, &s_trunk_ref, 1);
1165  ast_mutex_unlock(&sla.lock);
1166  if (!ringing_trunk) {
1167  /* This case happens in a bit of a race condition. If two stations answer
1168  * the outbound call at the same time, the first one will get connected to
1169  * the trunk. When the second one gets here, it will not see any trunks
1170  * ringing so we have no idea what to conect it to. So, we just hang up
1171  * on it. */
1172  ast_debug(1, "Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name);
1173  ast_dial_join(ringing_station->station->dial);
1174  ast_dial_destroy(ringing_station->station->dial);
1175  ringing_station->station->dial = NULL;
1176  sla_ringing_station_destroy(ringing_station);
1177  break;
1178  }
1179  /* Track the channel that answered this trunk */
1180  s_trunk_ref->chan = ast_dial_answered(ringing_station->station->dial);
1181  /* Actually answer the trunk */
1182  answer_trunk_chan(ringing_trunk->trunk->chan);
1183  sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
1184  /* Now, start a thread that will connect this station to the trunk. The rest of
1185  * the code here sets up the thread and ensures that it is able to save the arguments
1186  * before they are no longer valid since they are allocated on the stack. */
1187  ao2_ref(s_trunk_ref, 1);
1188  args.trunk_ref = s_trunk_ref;
1189  ao2_ref(ringing_station->station, 1);
1190  args.station = ringing_station->station;
1191  args.cond = &cond;
1192  args.cond_lock = &cond_lock;
1193  sla_ringing_trunk_destroy(ringing_trunk);
1194  sla_ringing_station_destroy(ringing_station);
1195  ast_mutex_init(&cond_lock);
1196  ast_cond_init(&cond, NULL);
1197  ast_mutex_lock(&cond_lock);
1198  ast_pthread_create_detached_background(&dont_care, NULL, run_station, &args);
1199  ast_cond_wait(&cond, &cond_lock);
1200  ast_mutex_unlock(&cond_lock);
1201  ast_mutex_destroy(&cond_lock);
1202  ast_cond_destroy(&cond);
1203  break;
1208  break;
1209  }
1210  if (dial_res == AST_DIAL_RESULT_ANSWERED) {
1211  /* Queue up reprocessing ringing trunks, and then ringing stations again */
1212  sla_queue_event(SLA_EVENT_RINGING_TRUNK);
1213  sla_queue_event(SLA_EVENT_DIAL_STATE);
1214  break;
1215  }
1216  }
1218 }
1219 
1220 /*! \brief Check to see if this station is already ringing
1221  * \note Assumes sla.lock is locked
1222  */
1223 static int sla_check_ringing_station(const struct sla_station *station)
1224 {
1225  struct sla_ringing_station *ringing_station;
1226 
1227  AST_LIST_TRAVERSE(&sla.ringing_stations, ringing_station, entry) {
1228  if (station == ringing_station->station) {
1229  return 1;
1230  }
1231  }
1232 
1233  return 0;
1234 }
1235 
1236 /*! \brief Check to see if this station has failed to be dialed in the past minute
1237  * \note assumes sla.lock is locked
1238  */
1239 static int sla_check_failed_station(const struct sla_station *station)
1240 {
1241  struct sla_failed_station *failed_station;
1242  int res = 0;
1243 
1244  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.failed_stations, failed_station, entry) {
1245  if (station != failed_station->station) {
1246  continue;
1247  }
1248  if (ast_tvdiff_ms(ast_tvnow(), failed_station->last_try) > 1000) {
1249  AST_LIST_REMOVE_CURRENT(entry);
1250  sla_failed_station_destroy(failed_station);
1251  break;
1252  }
1253  res = 1;
1254  }
1256 
1257  return res;
1258 }
1259 
1260 /*! \brief Ring a station
1261  * \note Assumes sla.lock is locked
1262  */
1263 static int sla_ring_station(struct sla_ringing_trunk *ringing_trunk, struct sla_station *station)
1264 {
1265  char *tech, *tech_data;
1266  struct ast_dial *dial;
1267  struct sla_ringing_station *ringing_station;
1268  enum ast_dial_result res;
1269  int caller_is_saved;
1270  struct ast_party_caller caller;
1271 
1272  if (!(dial = ast_dial_create())) {
1273  return -1;
1274  }
1275 
1276  ast_dial_set_state_callback(dial, sla_dial_state_callback);
1277  tech_data = ast_strdupa(station->device);
1278  tech = strsep(&tech_data, "/");
1279 
1280  if (ast_dial_append(dial, tech, tech_data, NULL) == -1) {
1281  ast_dial_destroy(dial);
1282  return -1;
1283  }
1284 
1285  /* Do we need to save off the caller ID data? */
1286  caller_is_saved = 0;
1287  if (!sla.attempt_callerid) {
1288  caller_is_saved = 1;
1289  caller = *ast_channel_caller(ringing_trunk->trunk->chan);
1290  ast_party_caller_init(ast_channel_caller(ringing_trunk->trunk->chan));
1291  }
1292 
1293  res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1);
1294 
1295  /* Restore saved caller ID */
1296  if (caller_is_saved) {
1297  ast_party_caller_free(ast_channel_caller(ringing_trunk->trunk->chan));
1298  ast_channel_caller_set(ringing_trunk->trunk->chan, &caller);
1299  }
1300 
1301  if (res != AST_DIAL_RESULT_TRYING) {
1302  struct sla_failed_station *failed_station;
1303  ast_dial_destroy(dial);
1304  if ((failed_station = sla_create_failed_station(station))) {
1305  AST_LIST_INSERT_HEAD(&sla.failed_stations, failed_station, entry);
1306  }
1307  return -1;
1308  }
1309  if (!(ringing_station = sla_create_ringing_station(station))) {
1310  ast_dial_join(dial);
1311  ast_dial_destroy(dial);
1312  return -1;
1313  }
1314 
1315  station->dial = dial;
1316 
1317  AST_LIST_INSERT_HEAD(&sla.ringing_stations, ringing_station, entry);
1318 
1319  return 0;
1320 }
1321 
1322 /*! \brief Check to see if a station is in use
1323  */
1324 static int sla_check_inuse_station(const struct sla_station *station)
1325 {
1326  struct sla_trunk_ref *trunk_ref;
1327 
1328  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
1329  if (trunk_ref->chan) {
1330  return 1;
1331  }
1332  }
1333 
1334  return 0;
1335 }
1336 
1337 static struct sla_trunk_ref *sla_find_trunk_ref(const struct sla_station *station, const struct sla_trunk *trunk)
1338 {
1339  struct sla_trunk_ref *trunk_ref = NULL;
1340 
1341  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
1342  if (trunk_ref->trunk == trunk) {
1343  break;
1344  }
1345  }
1346 
1347  ao2_ref(trunk_ref, 1);
1348 
1349  return trunk_ref;
1350 }
1351 
1352 /*! \brief Calculate the ring delay for a given ringing trunk on a station
1353  * \param station the station
1354  * \param ringing_trunk the trunk. If NULL, the highest priority ringing trunk will be used
1355  * \return the number of ms left before the delay is complete, or INT_MAX if there is no delay
1356  */
1357 static int sla_check_station_delay(struct sla_station *station, struct sla_ringing_trunk *ringing_trunk)
1358 {
1359  RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, ao2_cleanup);
1360  unsigned int delay = UINT_MAX;
1361  int time_left, time_elapsed;
1362 
1363  if (!ringing_trunk) {
1364  ringing_trunk = sla_choose_ringing_trunk(station, &trunk_ref, 0);
1365  } else {
1366  trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk);
1367  }
1368 
1369  if (!ringing_trunk || !trunk_ref) {
1370  return delay;
1371  }
1372 
1373  /* If this station has a ring delay specific to the highest priority
1374  * ringing trunk, use that. Otherwise, use the ring delay specified
1375  * globally for the station. */
1376  delay = trunk_ref->ring_delay;
1377  if (!delay) {
1378  delay = station->ring_delay;
1379  }
1380  if (!delay) {
1381  return INT_MAX;
1382  }
1383 
1384  time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
1385  time_left = (delay * 1000) - time_elapsed;
1386 
1387  return time_left;
1388 }
1389 
1390 /*! \brief Ring stations based on current set of ringing trunks
1391  * \note Assumes that sla.lock is locked
1392  */
1393 static void sla_ring_stations(void)
1394 {
1395  struct sla_station_ref *station_ref;
1396  struct sla_ringing_trunk *ringing_trunk;
1397 
1398  /* Make sure that every station that uses at least one of the ringing
1399  * trunks, is ringing. */
1400  AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1401  AST_LIST_TRAVERSE(&ringing_trunk->trunk->stations, station_ref, entry) {
1402  int time_left;
1403 
1404  /* Is this station already ringing? */
1405  if (sla_check_ringing_station(station_ref->station)) {
1406  continue;
1407  }
1408 
1409  /* Is this station already in a call? */
1410  if (sla_check_inuse_station(station_ref->station)) {
1411  continue;
1412  }
1413 
1414  /* Did we fail to dial this station earlier? If so, has it been
1415  * a minute since we tried? */
1416  if (sla_check_failed_station(station_ref->station)) {
1417  continue;
1418  }
1419 
1420  /* If this station already timed out while this trunk was ringing,
1421  * do not dial it again for this ringing trunk. */
1422  if (sla_check_timed_out_station(ringing_trunk, station_ref->station)) {
1423  continue;
1424  }
1425 
1426  /* Check for a ring delay in progress */
1427  time_left = sla_check_station_delay(station_ref->station, ringing_trunk);
1428  if (time_left != INT_MAX && time_left > 0) {
1429  continue;
1430  }
1431 
1432  /* It is time to make this station begin to ring. Do it! */
1433  sla_ring_station(ringing_trunk, station_ref->station);
1434  }
1435  }
1436  /* Now, all of the stations that should be ringing, are ringing. */
1437 }
1438 
1439 static void sla_hangup_stations(void)
1440 {
1441  struct sla_trunk_ref *trunk_ref;
1442  struct sla_ringing_station *ringing_station;
1443 
1444  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
1445  AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) {
1446  struct sla_ringing_trunk *ringing_trunk;
1447  ast_mutex_lock(&sla.lock);
1448  AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1449  if (trunk_ref->trunk == ringing_trunk->trunk) {
1450  break;
1451  }
1452  }
1453  ast_mutex_unlock(&sla.lock);
1454  if (ringing_trunk) {
1455  break;
1456  }
1457  }
1458  if (!trunk_ref) {
1459  AST_LIST_REMOVE_CURRENT(entry);
1460  ast_dial_join(ringing_station->station->dial);
1461  ast_dial_destroy(ringing_station->station->dial);
1462  ringing_station->station->dial = NULL;
1463  sla_ringing_station_destroy(ringing_station);
1464  }
1465  }
1467 }
1468 
1469 static void sla_handle_ringing_trunk_event(void)
1470 {
1471  ast_mutex_lock(&sla.lock);
1473  ast_mutex_unlock(&sla.lock);
1474 
1475  /* Find stations that shouldn't be ringing anymore. */
1476  sla_hangup_stations();
1477 }
1478 
1479 static void sla_handle_hold_event(struct sla_event *event)
1480 {
1481  ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1);
1482  event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME;
1483  ast_devstate_changed(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", event->station->name, event->trunk_ref->trunk->name);
1484  sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, INACTIVE_TRUNK_REFS, event->trunk_ref);
1485 
1486  if (event->trunk_ref->trunk->active_stations == 1) {
1487  /* The station putting it on hold is the only one on the call, so start
1488  * Music on hold to the trunk. */
1489  event->trunk_ref->trunk->on_hold = 1;
1490  ast_indicate(event->trunk_ref->trunk->chan, AST_CONTROL_HOLD);
1491  }
1492 
1493  ast_softhangup(event->trunk_ref->chan, AST_SOFTHANGUP_DEV);
1494  event->trunk_ref->chan = NULL;
1495 }
1496 
1497 /*! \brief Process trunk ring timeouts
1498  * \note Called with sla.lock locked
1499  * \return non-zero if a change to the ringing trunks was made
1500  */
1501 static int sla_calc_trunk_timeouts(unsigned int *timeout)
1502 {
1503  struct sla_ringing_trunk *ringing_trunk;
1504  int res = 0;
1505 
1506  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
1507  int time_left, time_elapsed;
1508  if (!ringing_trunk->trunk->ring_timeout) {
1509  continue;
1510  }
1511  time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
1512  time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed;
1513  if (time_left <= 0) {
1514  pbx_builtin_setvar_helper(ringing_trunk->trunk->chan, "SLATRUNK_STATUS", "RINGTIMEOUT");
1515  AST_LIST_REMOVE_CURRENT(entry);
1516  sla_stop_ringing_trunk(ringing_trunk);
1517  res = 1;
1518  continue;
1519  }
1520  if (time_left < *timeout) {
1521  *timeout = time_left;
1522  }
1523  }
1525 
1526  return res;
1527 }
1528 
1529 /*! \brief Process station ring timeouts
1530  * \note Called with sla.lock locked
1531  * \return non-zero if a change to the ringing stations was made
1532  */
1533 static int sla_calc_station_timeouts(unsigned int *timeout)
1534 {
1535  struct sla_ringing_trunk *ringing_trunk;
1536  struct sla_ringing_station *ringing_station;
1537  int res = 0;
1538 
1539  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_stations, ringing_station, entry) {
1540  unsigned int ring_timeout = 0;
1541  int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN;
1542  struct sla_trunk_ref *trunk_ref;
1543 
1544  /* If there are any ring timeouts specified for a specific trunk
1545  * on the station, then use the highest per-trunk ring timeout.
1546  * Otherwise, use the ring timeout set for the entire station. */
1547  AST_LIST_TRAVERSE(&ringing_station->station->trunks, trunk_ref, entry) {
1548  struct sla_station_ref *station_ref;
1549  int trunk_time_elapsed, trunk_time_left;
1550 
1551  AST_LIST_TRAVERSE(&sla.ringing_trunks, ringing_trunk, entry) {
1552  if (ringing_trunk->trunk == trunk_ref->trunk) {
1553  break;
1554  }
1555  }
1556  if (!ringing_trunk) {
1557  continue;
1558  }
1559 
1560  /* If there is a trunk that is ringing without a timeout, then the
1561  * only timeout that could matter is a global station ring timeout. */
1562  if (!trunk_ref->ring_timeout) {
1563  break;
1564  }
1565 
1566  /* This trunk on this station is ringing and has a timeout.
1567  * However, make sure this trunk isn't still ringing from a
1568  * previous timeout. If so, don't consider it. */
1569  AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, station_ref, entry) {
1570  if (station_ref->station == ringing_station->station) {
1571  break;
1572  }
1573  }
1574  if (station_ref) {
1575  continue;
1576  }
1577 
1578  trunk_time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_trunk->ring_begin);
1579  trunk_time_left = (trunk_ref->ring_timeout * 1000) - trunk_time_elapsed;
1580  if (trunk_time_left > final_trunk_time_left) {
1581  final_trunk_time_left = trunk_time_left;
1582  }
1583  }
1584 
1585  /* No timeout was found for ringing trunks, and no timeout for the entire station */
1586  if (final_trunk_time_left == INT_MIN && !ringing_station->station->ring_timeout) {
1587  continue;
1588  }
1589 
1590  /* Compute how much time is left for a global station timeout */
1591  if (ringing_station->station->ring_timeout) {
1592  ring_timeout = ringing_station->station->ring_timeout;
1593  time_elapsed = ast_tvdiff_ms(ast_tvnow(), ringing_station->ring_begin);
1594  time_left = (ring_timeout * 1000) - time_elapsed;
1595  }
1596 
1597  /* If the time left based on the per-trunk timeouts is smaller than the
1598  * global station ring timeout, use that. */
1599  if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) {
1600  time_left = final_trunk_time_left;
1601  }
1602 
1603  /* If there is no time left, the station needs to stop ringing */
1604  if (time_left <= 0) {
1605  AST_LIST_REMOVE_CURRENT(entry);
1606  sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT);
1607  res = 1;
1608  continue;
1609  }
1610 
1611  /* There is still some time left for this station to ring, so save that
1612  * timeout if it is the first event scheduled to occur */
1613  if (time_left < *timeout) {
1614  *timeout = time_left;
1615  }
1616  }
1618 
1619  return res;
1620 }
1621 
1622 /*! \brief Calculate the ring delay for a station
1623  * \note Assumes sla.lock is locked
1624  */
1625 static int sla_calc_station_delays(unsigned int *timeout)
1626 {
1627  struct sla_station *station;
1628  int res = 0;
1629  struct ao2_iterator i;
1630 
1631  i = ao2_iterator_init(sla_stations, 0);
1632  for (; (station = ao2_iterator_next(&i)); ao2_ref(station, -1)) {
1633  struct sla_ringing_trunk *ringing_trunk;
1634  int time_left;
1635 
1636  /* Ignore stations already ringing */
1637  if (sla_check_ringing_station(station)) {
1638  continue;
1639  }
1640 
1641  /* Ignore stations already on a call */
1642  if (sla_check_inuse_station(station)) {
1643  continue;
1644  }
1645 
1646  /* Ignore stations that don't have one of their trunks ringing */
1647  if (!(ringing_trunk = sla_choose_ringing_trunk(station, NULL, 0))) {
1648  continue;
1649  }
1650 
1651  if ((time_left = sla_check_station_delay(station, ringing_trunk)) == INT_MAX) {
1652  continue;
1653  }
1654 
1655  /* If there is no time left, then the station needs to start ringing.
1656  * Return non-zero so that an event will be queued up an event to
1657  * make that happen. */
1658  if (time_left <= 0) {
1659  res = 1;
1660  continue;
1661  }
1662 
1663  if (time_left < *timeout) {
1664  *timeout = time_left;
1665  }
1666  }
1668 
1669  return res;
1670 }
1671 
1672 /*! \brief Calculate the time until the next known event
1673  * \note Called with sla.lock locked */
1674 static int sla_process_timers(struct timespec *ts)
1675 {
1676  unsigned int timeout = UINT_MAX;
1677  struct timeval wait;
1678  unsigned int change_made = 0;
1679 
1680  /* Check for ring timeouts on ringing trunks */
1681  if (sla_calc_trunk_timeouts(&timeout)) {
1682  change_made = 1;
1683  }
1684 
1685  /* Check for ring timeouts on ringing stations */
1686  if (sla_calc_station_timeouts(&timeout)) {
1687  change_made = 1;
1688  }
1689 
1690  /* Check for station ring delays */
1691  if (sla_calc_station_delays(&timeout)) {
1692  change_made = 1;
1693  }
1694 
1695  /* queue reprocessing of ringing trunks */
1696  if (change_made) {
1697  sla_queue_event_nolock(SLA_EVENT_RINGING_TRUNK);
1698  }
1699 
1700  /* No timeout */
1701  if (timeout == UINT_MAX) {
1702  return 0;
1703  }
1704 
1705  if (ts) {
1706  wait = ast_tvadd(ast_tvnow(), ast_samp2tv(timeout, 1000));
1707  ts->tv_sec = wait.tv_sec;
1708  ts->tv_nsec = wait.tv_usec * 1000;
1709  }
1710 
1711  return 1;
1712 }
1713 
1714 static void sla_event_destroy(struct sla_event *event)
1715 {
1716  if (event->trunk_ref) {
1717  ao2_ref(event->trunk_ref, -1);
1718  event->trunk_ref = NULL;
1719  }
1720 
1721  if (event->station) {
1722  ao2_ref(event->station, -1);
1723  event->station = NULL;
1724  }
1725 
1726  ast_free(event);
1727 }
1728 
1729 static void *sla_thread(void *data)
1730 {
1731  struct sla_failed_station *failed_station;
1732  struct sla_ringing_station *ringing_station;
1733 
1734  ast_mutex_lock(&sla.lock);
1735 
1736  while (!sla.stop) {
1737  struct sla_event *event;
1738  struct timespec ts = { 0, };
1739  unsigned int have_timeout = 0;
1740 
1741  if (AST_LIST_EMPTY(&sla.event_q)) {
1742  if ((have_timeout = sla_process_timers(&ts))) {
1743  ast_cond_timedwait(&sla.cond, &sla.lock, &ts);
1744  } else {
1745  ast_cond_wait(&sla.cond, &sla.lock);
1746  }
1747  if (sla.stop) {
1748  break;
1749  }
1750  }
1751 
1752  if (have_timeout) {
1753  sla_process_timers(NULL);
1754  }
1755 
1756  while ((event = AST_LIST_REMOVE_HEAD(&sla.event_q, entry))) {
1757  ast_mutex_unlock(&sla.lock);
1758  switch (event->type) {
1759  case SLA_EVENT_HOLD:
1760  sla_handle_hold_event(event);
1761  break;
1762  case SLA_EVENT_DIAL_STATE:
1763  sla_handle_dial_state_event();
1764  break;
1766  sla_handle_ringing_trunk_event();
1767  break;
1768  }
1769  sla_event_destroy(event);
1770  ast_mutex_lock(&sla.lock);
1771  }
1772  }
1773 
1774  ast_mutex_unlock(&sla.lock);
1775 
1776  while ((ringing_station = AST_LIST_REMOVE_HEAD(&sla.ringing_stations, entry))) {
1777  sla_ringing_station_destroy(ringing_station);
1778  }
1779 
1780  while ((failed_station = AST_LIST_REMOVE_HEAD(&sla.failed_stations, entry))) {
1781  sla_failed_station_destroy(failed_station);
1782  }
1783 
1784  return NULL;
1785 }
1786 
1788  struct sla_trunk_ref *trunk_ref;
1789  struct sla_station *station;
1790  ast_mutex_t *cond_lock;
1791  ast_cond_t *cond;
1792 };
1793 
1794 static void *dial_trunk(void *data)
1795 {
1796  struct dial_trunk_args *args = data;
1797  struct ast_dial *dial;
1798  char *tech, *tech_data;
1799  enum ast_dial_result dial_res;
1800  char conf_name[MAX_CONFNUM];
1801  struct ast_flags conf_flags = { 0 };
1802  RAII_VAR(struct sla_trunk_ref *, trunk_ref, args->trunk_ref, ao2_cleanup);
1803  RAII_VAR(struct sla_station *, station, args->station, ao2_cleanup);
1804  int caller_is_saved;
1805  struct ast_party_caller caller;
1806  int last_state = 0;
1807  int current_state = 0;
1808 
1809  if (!(dial = ast_dial_create())) {
1810  ast_mutex_lock(args->cond_lock);
1811  ast_cond_signal(args->cond);
1812  ast_mutex_unlock(args->cond_lock);
1813  return NULL;
1814  }
1815 
1816  tech_data = ast_strdupa(trunk_ref->trunk->device);
1817  tech = strsep(&tech_data, "/");
1818  if (ast_dial_append(dial, tech, tech_data, NULL) == -1) {
1819  ast_mutex_lock(args->cond_lock);
1820  ast_cond_signal(args->cond);
1821  ast_mutex_unlock(args->cond_lock);
1822  ast_dial_destroy(dial);
1823  return NULL;
1824  }
1825 
1826  /* Do we need to save of the caller ID data? */
1827  caller_is_saved = 0;
1828  if (!sla.attempt_callerid) {
1829  caller_is_saved = 1;
1830  caller = *ast_channel_caller(trunk_ref->chan);
1831  ast_party_caller_init(ast_channel_caller(trunk_ref->chan));
1832  }
1833 
1834  dial_res = ast_dial_run(dial, trunk_ref->chan, 1);
1835 
1836  /* Restore saved caller ID */
1837  if (caller_is_saved) {
1838  ast_party_caller_free(ast_channel_caller(trunk_ref->chan));
1839  ast_channel_caller_set(trunk_ref->chan, &caller);
1840  }
1841 
1842  if (dial_res != AST_DIAL_RESULT_TRYING) {
1843  ast_mutex_lock(args->cond_lock);
1844  ast_cond_signal(args->cond);
1845  ast_mutex_unlock(args->cond_lock);
1846  ast_dial_destroy(dial);
1847  return NULL;
1848  }
1849 
1850  /* Wait for dial to end, while servicing the channel */
1851  while (ast_waitfor(trunk_ref->chan, 100)) {
1852  unsigned int done = 0;
1853  struct ast_frame *fr = ast_read(trunk_ref->chan);
1854 
1855  if (!fr) {
1856  ast_debug(1, "Channel %s did not return a frame, must have hung up\n", ast_channel_name(trunk_ref->chan));
1857  done = 1;
1858  break;
1859  }
1860  ast_frfree(fr); /* Ignore while dialing */
1861 
1862  switch ((dial_res = ast_dial_state(dial))) {
1864  trunk_ref->trunk->chan = ast_dial_answered(dial);
1870  done = 1;
1871  break;
1873  current_state = AST_CONTROL_PROGRESS;
1874  break;
1878  current_state = AST_CONTROL_RINGING;
1879  break;
1880  }
1881  if (done) {
1882  break;
1883  }
1884 
1885  /* check that SLA station that originated trunk call is still alive */
1886  if (station && ast_device_state(station->device) == AST_DEVICE_NOT_INUSE) {
1887  ast_debug(3, "Originating station device %s no longer active\n", station->device);
1888  trunk_ref->trunk->chan = NULL;
1889  break;
1890  }
1891 
1892  /* If trunk line state changed, send indication back to originating SLA Station channel */
1893  if (current_state != last_state) {
1894  ast_debug(3, "Indicating State Change %d to channel %s\n", current_state, ast_channel_name(trunk_ref->chan));
1895  ast_indicate(trunk_ref->chan, current_state);
1896  last_state = current_state;
1897  }
1898  }
1899 
1900  if (!trunk_ref->trunk->chan) {
1901  ast_mutex_lock(args->cond_lock);
1902  ast_cond_signal(args->cond);
1903  ast_mutex_unlock(args->cond_lock);
1904  ast_dial_join(dial);
1905  ast_dial_destroy(dial);
1906  return NULL;
1907  }
1908 
1909  snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name);
1910  ast_set_flag(&conf_flags, CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_MARKEDUSER | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_TRUNK);
1911 
1912  ast_mutex_lock(args->cond_lock);
1913  ast_cond_signal(args->cond);
1914  ast_mutex_unlock(args->cond_lock);
1915 
1916  ast_debug(2, "Trunk dial %s joining conference %s\n", trunk_ref->trunk->name, conf_name);
1917  conf_run(trunk_ref->trunk->chan, conf_name, &conf_flags, NULL);
1918 
1919  /* If the trunk is going away, it is definitely now IDLE. */
1920  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
1921 
1922  trunk_ref->trunk->chan = NULL;
1923  trunk_ref->trunk->on_hold = 0;
1924 
1925  ast_dial_join(dial);
1926  ast_dial_destroy(dial);
1927 
1928  return NULL;
1929 }
1930 
1931 /*!
1932  * \brief For a given station, choose the highest priority idle trunk
1933  * \pre sla_station is locked
1934  */
1935 static struct sla_trunk_ref *sla_choose_idle_trunk(const struct sla_station *station)
1936 {
1937  struct sla_trunk_ref *trunk_ref = NULL;
1938 
1939  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
1940  if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) {
1941  ao2_ref(trunk_ref, 1);
1942  break;
1943  }
1944  }
1945 
1946  return trunk_ref;
1947 }
1948 
1949 static int sla_station_exec(struct ast_channel *chan, const char *data)
1950 {
1951  char *station_name, *trunk_name;
1952  RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
1953  RAII_VAR(struct sla_trunk_ref *, trunk_ref, NULL, ao2_cleanup);
1954  char conf_name[MAX_CONFNUM];
1955  struct ast_flags conf_flags = { 0 };
1956 
1957  if (ast_strlen_zero(data)) {
1958  ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n");
1959  pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
1960  return 0;
1961  }
1962 
1963  trunk_name = ast_strdupa(data);
1964  station_name = strsep(&trunk_name, "_");
1965 
1966  if (ast_strlen_zero(station_name)) {
1967  ast_log(LOG_WARNING, "Invalid Arguments to SLAStation!\n");
1968  pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
1969  return 0;
1970  }
1971 
1972  station = sla_find_station(station_name);
1973 
1974  if (!station) {
1975  ast_log(LOG_WARNING, "Station '%s' not found!\n", station_name);
1976  pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "FAILURE");
1977  return 0;
1978  }
1979 
1980  ao2_lock(station);
1981  if (!ast_strlen_zero(trunk_name)) {
1982  trunk_ref = sla_find_trunk_ref_byname(station, trunk_name);
1983  } else {
1984  trunk_ref = sla_choose_idle_trunk(station);
1985  }
1986  ao2_unlock(station);
1987 
1988  if (!trunk_ref) {
1989  if (ast_strlen_zero(trunk_name)) {
1990  ast_log(LOG_NOTICE, "No trunks available for call.\n");
1991  } else {
1992  ast_log(LOG_NOTICE, "Can't join existing call on trunk '%s' due to access controls.\n", trunk_name);
1993  }
1994  pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
1995  return 0;
1996  }
1997 
1998  if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) {
1999  if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->hold_stations) == 1) {
2000  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
2001  } else {
2002  trunk_ref->state = SLA_TRUNK_STATE_UP;
2003  ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", station->name, trunk_ref->trunk->name);
2004  }
2005  } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) {
2006  struct sla_ringing_trunk *ringing_trunk;
2007 
2008  ast_mutex_lock(&sla.lock);
2009  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
2010  if (ringing_trunk->trunk == trunk_ref->trunk) {
2011  AST_LIST_REMOVE_CURRENT(entry);
2012  break;
2013  }
2014  }
2016  ast_mutex_unlock(&sla.lock);
2017 
2018  if (ringing_trunk) {
2019  answer_trunk_chan(ringing_trunk->trunk->chan);
2020  sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
2021 
2022  sla_ringing_trunk_destroy(ringing_trunk);
2023 
2024  /* Queue up reprocessing ringing trunks, and then ringing stations again */
2025  sla_queue_event(SLA_EVENT_RINGING_TRUNK);
2026  sla_queue_event(SLA_EVENT_DIAL_STATE);
2027  }
2028  }
2029 
2030  trunk_ref->chan = chan;
2031 
2032  if (!trunk_ref->trunk->chan) {
2033  ast_mutex_t cond_lock;
2034  ast_cond_t cond;
2035  pthread_t dont_care;
2036  struct dial_trunk_args args = {
2037  .trunk_ref = trunk_ref,
2038  .station = station,
2039  .cond_lock = &cond_lock,
2040  .cond = &cond,
2041  };
2042  ao2_ref(trunk_ref, 1);
2043  ao2_ref(station, 1);
2044  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
2045  /* Create a thread to dial the trunk and dump it into the conference.
2046  * However, we want to wait until the trunk has been dialed and the
2047  * conference is created before continuing on here.
2048  * Don't autoservice the channel or we'll have multiple threads
2049  * handling it. dial_trunk services the channel.
2050  */
2051  ast_mutex_init(&cond_lock);
2052  ast_cond_init(&cond, NULL);
2053  ast_mutex_lock(&cond_lock);
2054  ast_pthread_create_detached_background(&dont_care, NULL, dial_trunk, &args);
2055  ast_cond_wait(&cond, &cond_lock);
2056  ast_mutex_unlock(&cond_lock);
2057  ast_mutex_destroy(&cond_lock);
2058  ast_cond_destroy(&cond);
2059 
2060  if (!trunk_ref->trunk->chan) {
2061  ast_debug(1, "Trunk didn't get created. chan: %lx\n", (unsigned long) trunk_ref->trunk->chan);
2062  pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "CONGESTION");
2063  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
2064  trunk_ref->chan = NULL;
2065  return 0;
2066  }
2067  }
2068 
2069  if (ast_atomic_fetchadd_int((int *) &trunk_ref->trunk->active_stations, 1) == 0 &&
2070  trunk_ref->trunk->on_hold) {
2071  trunk_ref->trunk->on_hold = 0;
2072  ast_indicate(trunk_ref->trunk->chan, AST_CONTROL_UNHOLD);
2073  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
2074  }
2075 
2076  snprintf(conf_name, sizeof(conf_name), "SLA_%s", trunk_ref->trunk->name);
2077  ast_set_flag(&conf_flags, CONFFLAG_QUIET | CONFFLAG_MARKEDEXIT | CONFFLAG_PASS_DTMF | CONFFLAG_SLA_STATION);
2078  ast_answer(chan);
2079 
2080  ast_debug(2, "Station %s joining conference %s\n", station->name, conf_name);
2081  conf_run(chan, conf_name, &conf_flags, NULL);
2082 
2083  trunk_ref->chan = NULL;
2084  if (ast_atomic_dec_and_test((int *) &trunk_ref->trunk->active_stations) &&
2085  trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
2086  conf_kick_all(chan, conf_name);
2087  trunk_ref->trunk->hold_stations = 0;
2088  sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
2089  }
2090 
2091  pbx_builtin_setvar_helper(chan, "SLASTATION_STATUS", "SUCCESS");
2092 
2093  return 0;
2094 }
2095 
2096 static void sla_trunk_ref_destructor(void *obj)
2097 {
2098  struct sla_trunk_ref *trunk_ref = obj;
2099 
2100  if (trunk_ref->trunk) {
2101  ao2_ref(trunk_ref->trunk, -1);
2102  trunk_ref->trunk = NULL;
2103  }
2104 }
2105 
2106 static struct sla_trunk_ref *create_trunk_ref(struct sla_trunk *trunk)
2107 {
2108  struct sla_trunk_ref *trunk_ref;
2109 
2110  if (!(trunk_ref = ao2_alloc(sizeof(*trunk_ref), sla_trunk_ref_destructor))) {
2111  return NULL;
2112  }
2113 
2114  ao2_ref(trunk, 1);
2115  trunk_ref->trunk = trunk;
2116 
2117  return trunk_ref;
2118 }
2119 
2120 static struct sla_ringing_trunk *queue_ringing_trunk(struct sla_trunk *trunk)
2121 {
2122  struct sla_ringing_trunk *ringing_trunk;
2123 
2124  if (!(ringing_trunk = ast_calloc(1, sizeof(*ringing_trunk)))) {
2125  return NULL;
2126  }
2127 
2128  ao2_ref(trunk, 1);
2129  ringing_trunk->trunk = trunk;
2130  ringing_trunk->ring_begin = ast_tvnow();
2131 
2132  sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL);
2133 
2134  ast_mutex_lock(&sla.lock);
2135  AST_LIST_INSERT_HEAD(&sla.ringing_trunks, ringing_trunk, entry);
2136  ast_mutex_unlock(&sla.lock);
2137 
2138  sla_queue_event(SLA_EVENT_RINGING_TRUNK);
2139 
2140  return ringing_trunk;
2141 }
2142 
2143 static void sla_ringing_trunk_destroy(struct sla_ringing_trunk *ringing_trunk)
2144 {
2145  if (ringing_trunk->trunk) {
2146  ao2_ref(ringing_trunk->trunk, -1);
2147  ringing_trunk->trunk = NULL;
2148  }
2149 
2150  ast_free(ringing_trunk);
2151 }
2152 
2153 static int sla_trunk_exec(struct ast_channel *chan, const char *data)
2154 {
2155  char conf_name[MAX_CONFNUM];
2156  struct ast_flags conf_flags = { 0 };
2157  RAII_VAR(struct sla_trunk *, trunk, NULL, ao2_cleanup);
2158  struct sla_ringing_trunk *ringing_trunk;
2159  AST_DECLARE_APP_ARGS(args,
2160  AST_APP_ARG(trunk_name);
2161  AST_APP_ARG(options);
2162  );
2163  char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, };
2164  struct ast_flags opt_flags = { 0 };
2165  char *parse;
2166 
2167  if (ast_strlen_zero(data)) {
2168  ast_log(LOG_ERROR, "The SLATrunk application requires an argument, the trunk name\n");
2169  return -1;
2170  }
2171 
2172  parse = ast_strdupa(data);
2173  AST_STANDARD_APP_ARGS(args, parse);
2174  if (args.argc == 2) {
2175  if (ast_app_parse_options(sla_trunk_opts, &opt_flags, opts, args.options)) {
2176  ast_log(LOG_ERROR, "Error parsing options for SLATrunk\n");
2177  return -1;
2178  }
2179  }
2180 
2181  trunk = sla_find_trunk(args.trunk_name);
2182 
2183  if (!trunk) {
2184  ast_log(LOG_ERROR, "SLA Trunk '%s' not found!\n", args.trunk_name);
2185  pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
2186  return 0;
2187  }
2188 
2189  if (trunk->chan) {
2190  ast_log(LOG_ERROR, "Call came in on %s, but the trunk is already in use!\n", args.trunk_name);
2191  pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
2192  return 0;
2193  }
2194 
2195  trunk->chan = chan;
2196 
2197  if (!(ringing_trunk = queue_ringing_trunk(trunk))) {
2198  pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "FAILURE");
2199  return 0;
2200  }
2201 
2202  snprintf(conf_name, sizeof(conf_name), "SLA_%s", args.trunk_name);
2204 
2205  if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) {
2206  ast_indicate(chan, -1);
2207  ast_set_flag(&conf_flags, CONFFLAG_MOH);
2208  } else {
2210  }
2211 
2212  ast_debug(2, "Trunk %s joining conference %s\n", args.trunk_name, conf_name);
2213  conf_run(chan, conf_name, &conf_flags, opts);
2214  trunk->chan = NULL;
2215  trunk->on_hold = 0;
2216 
2217  sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
2218 
2219  if (!pbx_builtin_getvar_helper(chan, "SLATRUNK_STATUS")) {
2220  pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "SUCCESS");
2221  }
2222 
2223  /* Remove the entry from the list of ringing trunks if it is still there. */
2224  ast_mutex_lock(&sla.lock);
2225  AST_LIST_TRAVERSE_SAFE_BEGIN(&sla.ringing_trunks, ringing_trunk, entry) {
2226  if (ringing_trunk->trunk == trunk) {
2227  AST_LIST_REMOVE_CURRENT(entry);
2228  break;
2229  }
2230  }
2232  ast_mutex_unlock(&sla.lock);
2233  if (ringing_trunk) {
2234  sla_ringing_trunk_destroy(ringing_trunk);
2235  pbx_builtin_setvar_helper(chan, "SLATRUNK_STATUS", "UNANSWERED");
2236  /* Queue reprocessing of ringing trunks to make stations stop ringing
2237  * that shouldn't be ringing after this trunk stopped. */
2238  sla_queue_event(SLA_EVENT_RINGING_TRUNK);
2239  }
2240 
2241  return 0;
2242 }
2243 
2244 static enum ast_device_state sla_state(const char *data)
2245 {
2246  char *buf, *station_name, *trunk_name;
2247  RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
2248  struct sla_trunk_ref *trunk_ref;
2250 
2251  trunk_name = buf = ast_strdupa(data);
2252  station_name = strsep(&trunk_name, "_");
2253 
2254  station = sla_find_station(station_name);
2255  if (station) {
2256  ao2_lock(station);
2257  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2258  if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) {
2259  res = sla_state_to_devstate(trunk_ref->state);
2260  break;
2261  }
2262  }
2263  ao2_unlock(station);
2264  }
2265 
2266  if (res == AST_DEVICE_INVALID) {
2267  ast_log(LOG_ERROR, "Could not determine state for trunk %s on station %s!\n", trunk_name, station_name);
2268  }
2269 
2270  return res;
2271 }
2272 
2273 static int sla_trunk_release_refs(void *obj, void *arg, int flags)
2274 {
2275  struct sla_trunk *trunk = obj;
2276  struct sla_station_ref *station_ref;
2277 
2278  while ((station_ref = AST_LIST_REMOVE_HEAD(&trunk->stations, entry))) {
2279  ao2_ref(station_ref, -1);
2280  }
2281 
2282  return 0;
2283 }
2284 
2285 static int sla_station_release_refs(void *obj, void *arg, int flags)
2286 {
2287  struct sla_station *station = obj;
2288  struct sla_trunk_ref *trunk_ref;
2289 
2290  while ((trunk_ref = AST_LIST_REMOVE_HEAD(&station->trunks, entry))) {
2291  ao2_ref(trunk_ref, -1);
2292  }
2293 
2294  return 0;
2295 }
2296 
2297 static void sla_station_destructor(void *obj)
2298 {
2299  struct sla_station *station = obj;
2300 
2301  ast_debug(1, "sla_station destructor for '%s'\n", station->name);
2302 
2303  if (!ast_strlen_zero(station->autocontext)) {
2304  struct sla_trunk_ref *trunk_ref;
2305 
2306  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2307  char exten[AST_MAX_EXTENSION];
2308  char hint[AST_MAX_EXTENSION + 5];
2309  snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name);
2310  snprintf(hint, sizeof(hint), "SLA:%s", exten);
2311  ast_context_remove_extension(station->autocontext, exten, 1, sla_registrar);
2312  ast_context_remove_extension(station->autocontext, hint, PRIORITY_HINT, sla_registrar);
2313  }
2314  }
2315 
2316  sla_station_release_refs(station, NULL, 0);
2317 
2319 }
2320 
2321 static int sla_trunk_cmp(void *obj, void *arg, int flags)
2322 {
2323  struct sla_trunk *trunk = obj, *trunk2 = arg;
2324 
2325  return !strcasecmp(trunk->name, trunk2->name) ? CMP_MATCH | CMP_STOP : 0;
2326 }
2327 
2328 static int sla_station_cmp(void *obj, void *arg, int flags)
2329 {
2330  struct sla_station *station = obj, *station2 = arg;
2331 
2332  return !strcasecmp(station->name, station2->name) ? CMP_MATCH | CMP_STOP : 0;
2333 }
2334 
2335 static void sla_destroy(void)
2336 {
2337  if (sla.thread != AST_PTHREADT_NULL) {
2338  ast_mutex_lock(&sla.lock);
2339  sla.stop = 1;
2340  ast_cond_signal(&sla.cond);
2341  ast_mutex_unlock(&sla.lock);
2342  pthread_join(sla.thread, NULL);
2343  }
2344 
2345  /* Drop any created contexts from the dialplan */
2346  ast_context_destroy(NULL, sla_registrar);
2347 
2348  ast_mutex_destroy(&sla.lock);
2349  ast_cond_destroy(&sla.cond);
2350 
2351  ao2_callback(sla_trunks, 0, sla_trunk_release_refs, NULL);
2352  ao2_callback(sla_stations, 0, sla_station_release_refs, NULL);
2353 
2354  ao2_ref(sla_trunks, -1);
2355  sla_trunks = NULL;
2356 
2357  ao2_ref(sla_stations, -1);
2358  sla_stations = NULL;
2359 }
2360 
2361 static int sla_check_device(const char *device)
2362 {
2363  char *tech, *tech_data;
2364 
2365  tech_data = ast_strdupa(device);
2366  tech = strsep(&tech_data, "/");
2367 
2368  if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) {
2369  return -1;
2370  }
2371 
2372  return 0;
2373 }
2374 
2375 static void sla_trunk_destructor(void *obj)
2376 {
2377  struct sla_trunk *trunk = obj;
2378 
2379  ast_debug(1, "sla_trunk destructor for '%s'\n", trunk->name);
2380 
2381  if (!ast_strlen_zero(trunk->autocontext)) {
2382  ast_context_remove_extension(trunk->autocontext, "s", 1, sla_registrar);
2383  }
2384 
2385  sla_trunk_release_refs(trunk, NULL, 0);
2386 
2388 }
2389 
2390 static int sla_build_trunk(struct ast_config *cfg, const char *cat)
2391 {
2392  RAII_VAR(struct sla_trunk *, trunk, NULL, ao2_cleanup);
2393  struct ast_variable *var;
2394  const char *dev;
2395  int existing_trunk = 0;
2396 
2397  if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) {
2398  ast_log(LOG_ERROR, "SLA Trunk '%s' defined with no device!\n", cat);
2399  return -1;
2400  }
2401 
2402  if (sla_check_device(dev)) {
2403  ast_log(LOG_ERROR, "SLA Trunk '%s' defined with invalid device '%s'!\n", cat, dev);
2404  return -1;
2405  }
2406 
2407  if ((trunk = sla_find_trunk(cat))) {
2408  trunk->mark = 0;
2409  existing_trunk = 1;
2410  } else if ((trunk = ao2_alloc(sizeof(*trunk), sla_trunk_destructor))) {
2411  if (ast_string_field_init(trunk, 32)) {
2412  return -1;
2413  }
2414  ast_string_field_set(trunk, name, cat);
2415  } else {
2416  return -1;
2417  }
2418 
2419  ao2_lock(trunk);
2420 
2421  ast_string_field_set(trunk, device, dev);
2422 
2423  for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
2424  if (!strcasecmp(var->name, "autocontext")) {
2425  ast_string_field_set(trunk, autocontext, var->value);
2426  } else if (!strcasecmp(var->name, "ringtimeout")) {
2427  if (sscanf(var->value, "%30u", &trunk->ring_timeout) != 1) {
2428  ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for trunk '%s'\n", var->value, trunk->name);
2429  trunk->ring_timeout = 0;
2430  }
2431  } else if (!strcasecmp(var->name, "barge")) {
2432  trunk->barge_disabled = ast_false(var->value);
2433  } else if (!strcasecmp(var->name, "hold")) {
2434  if (!strcasecmp(var->value, "private")) {
2435  trunk->hold_access = SLA_HOLD_PRIVATE;
2436  } else if (!strcasecmp(var->value, "open")) {
2437  trunk->hold_access = SLA_HOLD_OPEN;
2438  } else {
2439  ast_log(LOG_WARNING, "Invalid value '%s' for hold on trunk %s\n", var->value, trunk->name);
2440  }
2441  } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) {
2442  ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", var->name, var->lineno, SLA_CONFIG_FILE);
2443  }
2444  }
2445 
2446  ao2_unlock(trunk);
2447 
2448  if (!ast_strlen_zero(trunk->autocontext)) {
2449  if (!ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar)) {
2450  ast_log(LOG_ERROR, "Failed to automatically find or create context '%s' for SLA!\n", trunk->autocontext);
2451  return -1;
2452  }
2453 
2454  if (ast_add_extension(trunk->autocontext, 0 /* don't replace */, "s", 1,
2455  NULL, NULL, slatrunk_app, ast_strdup(trunk->name), ast_free_ptr, sla_registrar)) {
2456  ast_log(LOG_ERROR, "Failed to automatically create extension for trunk '%s'!\n", trunk->name);
2457  return -1;
2458  }
2459  }
2460 
2461  if (!existing_trunk) {
2462  ao2_link(sla_trunks, trunk);
2463  }
2464 
2465  return 0;
2466 }
2467 
2468 /*!
2469  * \internal
2470  * \pre station is not locked
2471  */
2472 static void sla_add_trunk_to_station(struct sla_station *station, struct ast_variable *var)
2473 {
2474  RAII_VAR(struct sla_trunk *, trunk, NULL, ao2_cleanup);
2475  struct sla_trunk_ref *trunk_ref = NULL;
2476  struct sla_station_ref *station_ref;
2477  char *trunk_name, *options, *cur;
2478  int existing_trunk_ref = 0;
2479  int existing_station_ref = 0;
2480 
2481  options = ast_strdupa(var->value);
2482  trunk_name = strsep(&options, ",");
2483 
2484  trunk = sla_find_trunk(trunk_name);
2485  if (!trunk) {
2486  ast_log(LOG_ERROR, "Trunk '%s' not found!\n", var->value);
2487  return;
2488  }
2489 
2490  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2491  if (trunk_ref->trunk == trunk) {
2492  trunk_ref->mark = 0;
2493  existing_trunk_ref = 1;
2494  break;
2495  }
2496  }
2497 
2498  if (!trunk_ref && !(trunk_ref = create_trunk_ref(trunk))) {
2499  return;
2500  }
2501 
2502  trunk_ref->state = SLA_TRUNK_STATE_IDLE;
2503 
2504  while ((cur = strsep(&options, ","))) {
2505  char *name, *value = cur;
2506  name = strsep(&value, "=");
2507  if (!strcasecmp(name, "ringtimeout")) {
2508  if (sscanf(value, "%30u", &trunk_ref->ring_timeout) != 1) {
2509  ast_log(LOG_WARNING, "Invalid ringtimeout value '%s' for trunk '%s' on station '%s'\n", value, trunk->name, station->name);
2510  trunk_ref->ring_timeout = 0;
2511  }
2512  } else if (!strcasecmp(name, "ringdelay")) {
2513  if (sscanf(value, "%30u", &trunk_ref->ring_delay) != 1) {
2514  ast_log(LOG_WARNING, "Invalid ringdelay value '%s' for trunk '%s' on station '%s'\n", value, trunk->name, station->name);
2515  trunk_ref->ring_delay = 0;
2516  }
2517  } else {
2518  ast_log(LOG_WARNING, "Invalid option '%s' for trunk '%s' on station '%s'\n", name, trunk->name, station->name);
2519  }
2520  }
2521 
2522  AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
2523  if (station_ref->station == station) {
2524  station_ref->mark = 0;
2525  existing_station_ref = 1;
2526  break;
2527  }
2528  }
2529 
2530  if (!station_ref && !(station_ref = sla_create_station_ref(station))) {
2531  if (!existing_trunk_ref) {
2532  ao2_ref(trunk_ref, -1);
2533  } else {
2534  trunk_ref->mark = 1;
2535  }
2536  return;
2537  }
2538 
2539  if (!existing_station_ref) {
2540  ao2_lock(trunk);
2541  AST_LIST_INSERT_TAIL(&trunk->stations, station_ref, entry);
2542  ast_atomic_fetchadd_int((int *) &trunk->num_stations, 1);
2543  ao2_unlock(trunk);
2544  }
2545 
2546  if (!existing_trunk_ref) {
2547  ao2_lock(station);
2548  AST_LIST_INSERT_TAIL(&station->trunks, trunk_ref, entry);
2549  ao2_unlock(station);
2550  }
2551 }
2552 
2553 static int sla_build_station(struct ast_config *cfg, const char *cat)
2554 {
2555  RAII_VAR(struct sla_station *, station, NULL, ao2_cleanup);
2556  struct ast_variable *var;
2557  const char *dev;
2558  int existing_station = 0;
2559 
2560  if (!(dev = ast_variable_retrieve(cfg, cat, "device"))) {
2561  ast_log(LOG_ERROR, "SLA Station '%s' defined with no device!\n", cat);
2562  return -1;
2563  }
2564 
2565  if ((station = sla_find_station(cat))) {
2566  station->mark = 0;
2567  existing_station = 1;
2568  } else if ((station = ao2_alloc(sizeof(*station), sla_station_destructor))) {
2569  if (ast_string_field_init(station, 32)) {
2570  return -1;
2571  }
2572  ast_string_field_set(station, name, cat);
2573  } else {
2574  return -1;
2575  }
2576 
2577  ao2_lock(station);
2578 
2579  ast_string_field_set(station, device, dev);
2580 
2581  for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
2582  if (!strcasecmp(var->name, "trunk")) {
2583  ao2_unlock(station);
2584  sla_add_trunk_to_station(station, var);
2585  ao2_lock(station);
2586  } else if (!strcasecmp(var->name, "autocontext")) {
2587  ast_string_field_set(station, autocontext, var->value);
2588  } else if (!strcasecmp(var->name, "ringtimeout")) {
2589  if (sscanf(var->value, "%30u", &station->ring_timeout) != 1) {
2590  ast_log(LOG_WARNING, "Invalid ringtimeout '%s' specified for station '%s'\n", var->value, station->name);
2591  station->ring_timeout = 0;
2592  }
2593  } else if (!strcasecmp(var->name, "ringdelay")) {
2594  if (sscanf(var->value, "%30u", &station->ring_delay) != 1) {
2595  ast_log(LOG_WARNING, "Invalid ringdelay '%s' specified for station '%s'\n", var->value, station->name);
2596  station->ring_delay = 0;
2597  }
2598  } else if (!strcasecmp(var->name, "hold")) {
2599  if (!strcasecmp(var->value, "private")) {
2600  station->hold_access = SLA_HOLD_PRIVATE;
2601  } else if (!strcasecmp(var->value, "open")) {
2602  station->hold_access = SLA_HOLD_OPEN;
2603  } else {
2604  ast_log(LOG_WARNING, "Invalid value '%s' for hold on station %s\n", var->value, station->name);
2605  }
2606  } else if (strcasecmp(var->name, "type") && strcasecmp(var->name, "device")) {
2607  ast_log(LOG_ERROR, "Invalid option '%s' specified at line %d of %s!\n", var->name, var->lineno, SLA_CONFIG_FILE);
2608  }
2609  }
2610 
2611  ao2_unlock(station);
2612 
2613  if (!ast_strlen_zero(station->autocontext)) {
2614  struct sla_trunk_ref *trunk_ref;
2615 
2616  if (!ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar)) {
2617  ast_log(LOG_ERROR, "Failed to automatically find or create context '%s' for SLA!\n", station->autocontext);
2618  return -1;
2619  }
2620  /* The extension for when the handset goes off-hook.
2621  * exten => station1,1,SLAStation(station1) */
2622  if (ast_add_extension(station->autocontext, 0 /* don't replace */, station->name, 1,
2623  NULL, NULL, slastation_app, ast_strdup(station->name), ast_free_ptr, sla_registrar)) {
2624  ast_log(LOG_ERROR, "Failed to automatically create extension for trunk '%s'!\n", station->name);
2625  return -1;
2626  }
2627  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2628  char exten[AST_MAX_EXTENSION];
2629  char hint[AST_MAX_EXTENSION + 5];
2630  snprintf(exten, sizeof(exten), "%s_%s", station->name, trunk_ref->trunk->name);
2631  snprintf(hint, sizeof(hint), "SLA:%s", exten);
2632  /* Extension for this line button
2633  * exten => station1_line1,1,SLAStation(station1_line1) */
2634  if (ast_add_extension(station->autocontext, 0 /* don't replace */, exten, 1,
2635  NULL, NULL, slastation_app, ast_strdup(exten), ast_free_ptr, sla_registrar)) {
2636  ast_log(LOG_ERROR, "Failed to automatically create extension for trunk '%s'!\n", station->name);
2637  return -1;
2638  }
2639  /* Hint for this line button
2640  * exten => station1_line1,hint,SLA:station1_line1 */
2641  if (ast_add_extension(station->autocontext, 0 /* don't replace */, exten, PRIORITY_HINT,
2642  NULL, NULL, hint, NULL, NULL, sla_registrar)) {
2643  ast_log(LOG_ERROR, "Failed to automatically create hint for trunk '%s'!\n", station->name);
2644  return -1;
2645  }
2646  }
2647  }
2648 
2649  if (!existing_station) {
2650  ao2_link(sla_stations, station);
2651  }
2652 
2653  return 0;
2654 }
2655 
2656 static int sla_trunk_mark(void *obj, void *arg, int flags)
2657 {
2658  struct sla_trunk *trunk = obj;
2659  struct sla_station_ref *station_ref;
2660 
2661  ao2_lock(trunk);
2662 
2663  trunk->mark = 1;
2664 
2665  AST_LIST_TRAVERSE(&trunk->stations, station_ref, entry) {
2666  station_ref->mark = 1;
2667  }
2668 
2669  ao2_unlock(trunk);
2670 
2671  return 0;
2672 }
2673 
2674 static int sla_station_mark(void *obj, void *arg, int flags)
2675 {
2676  struct sla_station *station = obj;
2677  struct sla_trunk_ref *trunk_ref;
2678 
2679  ao2_lock(station);
2680 
2681  station->mark = 1;
2682 
2683  AST_LIST_TRAVERSE(&station->trunks, trunk_ref, entry) {
2684  trunk_ref->mark = 1;
2685  }
2686 
2687  ao2_unlock(station);
2688 
2689  return 0;
2690 }
2691 
2692 static int sla_trunk_is_marked(void *obj, void *arg, int flags)
2693 {
2694  struct sla_trunk *trunk = obj;
2695 
2696  ao2_lock(trunk);
2697 
2698  if (trunk->mark) {
2699  /* Only remove all of the station references if the trunk itself is going away */
2700  sla_trunk_release_refs(trunk, NULL, 0);
2701  } else {
2702  struct sla_station_ref *station_ref;
2703 
2704  /* Otherwise only remove references to stations no longer in the config */
2705  AST_LIST_TRAVERSE_SAFE_BEGIN(&trunk->stations, station_ref, entry) {
2706  if (!station_ref->mark) {
2707  continue;
2708  }
2709  AST_LIST_REMOVE_CURRENT(entry);
2710  ao2_ref(station_ref, -1);
2711  }
2713  }
2714 
2715  ao2_unlock(trunk);
2716 
2717  return trunk->mark ? CMP_MATCH : 0;
2718 }
2719 
2720 static int sla_station_is_marked(void *obj, void *arg, int flags)
2721 {
2722  struct sla_station *station = obj;
2723 
2724  ao2_lock(station);
2725 
2726  if (station->mark) {
2727  /* Only remove all of the trunk references if the station itself is going away */
2728  sla_station_release_refs(station, NULL, 0);
2729  } else {
2730  struct sla_trunk_ref *trunk_ref;
2731 
2732  /* Otherwise only remove references to trunks no longer in the config */
2733  AST_LIST_TRAVERSE_SAFE_BEGIN(&station->trunks, trunk_ref, entry) {
2734  if (!trunk_ref->mark) {
2735  continue;
2736  }
2737  AST_LIST_REMOVE_CURRENT(entry);
2738  ao2_ref(trunk_ref, -1);
2739  }
2741  }
2742 
2743  ao2_unlock(station);
2744 
2745  return station->mark ? CMP_MATCH : 0;
2746 }
2747 
2748 static int sla_in_use(void)
2749 {
2750  return ao2_container_count(sla_trunks) || ao2_container_count(sla_stations);
2751 }
2752 
2753 static int sla_load_config(int reload)
2754 {
2755  struct ast_config *cfg;
2756  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2757  const char *cat = NULL;
2758  int res = 0;
2759  const char *val;
2760 
2761  if (!reload) {
2762  ast_mutex_init(&sla.lock);
2763  ast_cond_init(&sla.cond, NULL);
2764  sla_trunks = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, sla_trunk_cmp);
2765  sla_stations = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, sla_station_cmp);
2766  }
2767 
2768  if (!(cfg = ast_config_load(SLA_CONFIG_FILE, config_flags))) {
2769  return 0; /* Treat no config as normal */
2770  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2771  return 0;
2772  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2773  ast_log(LOG_ERROR, "Config file " SLA_CONFIG_FILE " is in an invalid format. Aborting.\n");
2774  return 0;
2775  }
2776 
2777  if (reload) {
2778  ao2_callback(sla_trunks, 0, sla_trunk_mark, NULL);
2779  ao2_callback(sla_stations, 0, sla_station_mark, NULL);
2780  }
2781 
2782  if ((val = ast_variable_retrieve(cfg, "general", "attemptcallerid"))) {
2783  sla.attempt_callerid = ast_true(val);
2784  }
2785 
2786  while ((cat = ast_category_browse(cfg, cat)) && !res) {
2787  const char *type;
2788  if (!strcasecmp(cat, "general")) {
2789  continue;
2790  }
2791  if (!(type = ast_variable_retrieve(cfg, cat, "type"))) {
2792  ast_log(LOG_WARNING, "Invalid entry in %s defined with no type!\n", SLA_CONFIG_FILE);
2793  continue;
2794  }
2795  if (!strcasecmp(type, "trunk")) {
2796  res = sla_build_trunk(cfg, cat);
2797  } else if (!strcasecmp(type, "station")) {
2798  res = sla_build_station(cfg, cat);
2799  } else {
2800  ast_log(LOG_WARNING, "Entry in %s defined with invalid type '%s'!\n", SLA_CONFIG_FILE, type);
2801  }
2802  }
2803 
2804  ast_config_destroy(cfg);
2805 
2806  if (reload) {
2807  ao2_callback(sla_trunks, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, sla_trunk_is_marked, NULL);
2808  ao2_callback(sla_stations, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, sla_station_is_marked, NULL);
2809  }
2810 
2811  /* Start SLA event processing thread once SLA has been configured. */
2812  if (sla.thread == AST_PTHREADT_NULL && sla_in_use()) {
2813  ast_pthread_create(&sla.thread, NULL, sla_thread, NULL);
2814  }
2815 
2816  return res;
2817 }
2818 
2819 static int load_config(int reload)
2820 {
2821  return sla_load_config(reload);
2822 }
2823 
2824 static int unload_module(void)
2825 {
2826  int res = 0;
2827 
2828  ast_cli_unregister_multiple(cli_sla, ARRAY_LEN(cli_sla));
2829  res |= ast_unregister_application(slastation_app);
2830  res |= ast_unregister_application(slatrunk_app);
2831 
2832  ast_devstate_prov_del("SLA");
2833 
2834  sla_destroy();
2835 
2836  return res;
2837 }
2838 
2839 /*!
2840  * \brief Load the module
2841  *
2842  * Module loading including tests for configuration or dependencies.
2843  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
2844  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
2845  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
2846  * configuration file or other non-critical problem return
2847  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
2848  */
2849 static int load_module(void)
2850 {
2851  int res = 0;
2852 
2853  res |= load_config(0);
2854 
2855  ast_cli_register_multiple(cli_sla, ARRAY_LEN(cli_sla));
2856  res |= ast_register_application_xml(slastation_app, sla_station_exec);
2857  res |= ast_register_application_xml(slatrunk_app, sla_trunk_exec);
2858 
2859  res |= ast_devstate_prov_add("SLA", sla_state);
2860 
2861  return res;
2862 }
2863 
2864 static int reload(void)
2865 {
2866  return load_config(1);
2867 }
2868 
2869 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Shared Line Appearances",
2870  .support_level = AST_MODULE_SUPPORT_EXTENDED,
2871  .load = load_module,
2872  .unload = unload_module,
2873  .reload = reload,
2874  .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
2875 );
const char * type
Definition: datastore.h:32
unsigned int active_stations
Definition: app_sla.c:231
struct ast_variable * next
static int sla_calc_trunk_timeouts(unsigned int *timeout)
Process trunk ring timeouts.
Definition: app_sla.c:1501
Main Channel structure associated with a channel.
ast_device_state
Device States.
Definition: devicestate.h:52
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
static int sla_check_ringing_station(const struct sla_station *station)
Check to see if this station is already ringing.
Definition: app_sla.c:1223
sla_hold_access
Definition: app_sla.c:171
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
unsigned int ring_timeout
Definition: app_sla.c:263
Main dialing structure. Contains global options, channels being dialed, and more! ...
Definition: dial.c:48
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
unsigned int mark
Definition: app_sla.c:269
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
unsigned int mark
Definition: app_sla.c:203
Device state management.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
static int load_module(void)
Load the module.
Definition: app_sla.c:2849
static struct sla_ringing_trunk * sla_choose_ringing_trunk(struct sla_station *station, struct sla_trunk_ref **trunk_ref, int rm)
Choose the highest priority ringing trunk for a station.
Definition: app_sla.c:1099
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
#define OBJ_POINTER
Definition: astobj2.h:1150
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
descriptor for a cli entry.
Definition: cli.h:171
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
Definition: framehook.h:151
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
Structure for variables, used for configurations and for channel variables.
pthread_t thread
Definition: app_sla.c:329
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4257
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
A station that is ringing.
Definition: app_sla.c:317
Structure for a data store type.
Definition: datastore.h:31
Definition: astman.c:222
Dialing API.
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
Definition: channel.c:2015
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
A reference to a station.
Definition: app_sla.c:214
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
Structure for a data store object.
Definition: datastore.h:64
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
unsigned int ring_delay
Definition: app_sla.c:198
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
void ast_free_ptr(void *ptr)
free() wrapper
Definition: main/astmm.c:1739
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
unsigned int hold_access
Definition: app_sla.c:201
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
int ast_raw_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2690
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
static int sla_process_timers(struct timespec *ts)
Calculate the time until the next known event.
Definition: app_sla.c:1674
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:4948
Utility functions.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
static struct sla_trunk_ref * sla_find_trunk_ref_byname(const struct sla_station *station, const char *name)
Find a trunk reference on a station by name.
Definition: app_sla.c:759
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1269
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
unsigned int mark
Definition: app_sla.c:246
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
ast_mutex_t lock
static int sla_calc_station_delays(unsigned int *timeout)
Calculate the ring delay for a station.
Definition: app_sla.c:1625
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
General Asterisk PBX channel definitions.
struct timeval ring_begin
Definition: app_sla.c:306
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
Definition: dial.c:1017
unsigned int on_hold
Definition: app_sla.c:244
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
Framehook to support HOLD within the conference.
Definition: app_sla.c:605
A trunk that is ringing.
Definition: app_sla.c:303
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define AST_MAX_EXTENSION
Definition: channel.h:134
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
Caller Party information.
Definition: channel.h:418
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
int ast_atomic_dec_and_test(volatile int *p)
decrement *p by 1 and return true if the variable has reached 0.
Definition: lock.h:767
unsigned int barge_disabled
Definition: app_sla.c:238
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define PRIORITY_HINT
Definition: pbx.h:54
struct timeval ring_begin
Definition: app_sla.c:320
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1008
Core PBX routines and definitions.
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
ast_frame_type
Frame types.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:225
static int sla_check_timed_out_station(const struct sla_ringing_trunk *ringing_trunk, const struct sla_station *station)
Check to see if dialing this station already timed out for this ringing trunk.
Definition: app_sla.c:1078
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
Definition: pbx_app.c:501
unsigned int num_stations
Definition: app_sla.c:229
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
Support for dynamic strings.
Definition: strings.h:623
Media Format Bitfield Compatibility API.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
unsigned int hold_access
Definition: app_sla.c:241
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
static void sla_queue_event_conf(enum sla_event_type type, struct ast_channel *chan, const char *confname)
Queue a SLA event from the conference.
Definition: app_sla.c:561
static int sla_check_failed_station(const struct sla_station *station)
Check to see if this station has failed to be dialed in the past minute.
Definition: app_sla.c:1239
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
Definition: dial.c:977
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
unsigned int stop
Definition: res_smdi.c:217
static int sla_check_station_delay(struct sla_station *station, struct sla_ringing_trunk *ringing_trunk)
Calculate the ring delay for a given ringing trunk on a station.
Definition: app_sla.c:1357
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
unsigned int hold_stations
Definition: app_sla.c:233
Structure used to handle boolean flags.
Definition: utils.h:199
static int sla_ring_station(struct sla_ringing_trunk *ringing_trunk, struct sla_station *station)
Ring a station.
Definition: app_sla.c:1263
const char * usage
Definition: cli.h:177
static struct sla_trunk_ref * sla_choose_idle_trunk(const struct sla_station *station)
For a given station, choose the highest priority idle trunk.
Definition: app_sla.c:1935
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
void * data
Definition: datastore.h:66
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6928
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Standard Command Line Interface.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: utils.c:2216
A station that failed to be dialed.
Definition: app_sla.c:296
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2805
Data structure associated with a single frame of data.
static int sla_framehook_consume(void *data, enum ast_frame_type type)
Callback function which informs upstream if we are consuming a frame of a specific type...
Definition: app_sla.c:655
Internal Asterisk hangup causes.
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8221
static int sla_check_inuse_station(const struct sla_station *station)
Check to see if a station is in use.
Definition: app_sla.c:1324
Definition: search.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
enum ast_frame_type frametype
Generic container type.
A station's reference to a trunk.
Definition: app_sla.c:255
unsigned int ring_timeout
Definition: app_sla.c:194
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6149
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
static int sla_calc_station_timeouts(unsigned int *timeout)
Process station ring timeouts.
Definition: app_sla.c:1533
static struct @66 sla
A structure for data used by the sla thread.
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
Definition: channel.c:1978
unsigned int mark
Definition: app_sla.c:218
static void sla_ring_stations(void)
Ring stations based on current set of ringing trunks.
Definition: app_sla.c:1393
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
unsigned int ring_delay
Definition: app_sla.c:267
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
Structure for mutex and tracking information.
Definition: lock.h:135
sla_event_type
Event types that can be queued up for the SLA thread.
Definition: app_sla.c:278
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
unsigned int attempt_callerid
Definition: app_sla.c:339