124 #define SLA_CONFIG_FILE "sla.conf"
125 #define MAX_CONFNUM 80
127 static const char *
const slastation_app =
"SLAStation";
128 static const char *
const slatrunk_app =
"SLATrunk";
141 CONFFLAG_SLA_STATION = (1 << 5),
142 CONFFLAG_SLA_TRUNK = (1 << 6),
146 SLA_TRUNK_OPT_MOH = (1 << 0),
150 SLA_TRUNK_OPT_ARG_MOH_CLASS = 0,
151 SLA_TRUNK_OPT_ARG_ARRAY_SIZE = 1,
158 enum sla_which_trunk_refs {
163 enum sla_trunk_state {
164 SLA_TRUNK_STATE_IDLE,
165 SLA_TRUNK_STATE_RINGING,
167 SLA_TRUNK_STATE_ONHOLD,
168 SLA_TRUNK_STATE_ONHOLD_BYME,
235 unsigned int ring_timeout;
258 enum sla_trunk_state
state;
275 static const char sla_registrar[] =
"SLA";
298 struct timeval last_try;
311 enum sla_station_hangup {
312 SLA_STATION_HANGUP_NORMAL,
313 SLA_STATION_HANGUP_TIMEOUT,
341 .thread = AST_PTHREADT_NULL,
344 static const char *sla_hold_str(
unsigned int hold_access)
346 const char *
hold =
"Unknown";
348 switch (hold_access) {
368 e->
command =
"sla show trunks";
370 "Usage: sla show trunks\n"
371 " This will list all trunks defined in sla.conf\n";
378 "=============================================================\n"
379 "=== Configured SLA Trunks ===================================\n"
380 "=============================================================\n"
383 for (; (trunk = ao2_iterator_next(&i));
ao2_ref(trunk, -1)) {
385 char ring_timeout[23] =
"(none)";
389 if (trunk->ring_timeout) {
390 snprintf(ring_timeout,
sizeof(ring_timeout),
"%u Seconds", trunk->ring_timeout);
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)"),
408 ast_cli(a->fd,
"=== ==> Station name: %s\n", station_ref->station->name);
411 ast_cli(a->fd,
"=== ---------------------------------------------------------\n===\n");
416 ast_cli(a->fd,
"=============================================================\n\n");
421 static const char *trunkstate2str(
enum sla_trunk_state
state)
423 #define S(e) case e: return # e;
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)
431 return "Uknown State";
442 e->
command =
"sla show stations";
444 "Usage: sla show stations\n"
445 " This will list all stations defined in sla.conf\n";
452 "=============================================================\n"
453 "=== Configured SLA Stations =================================\n"
454 "=============================================================\n"
457 for (; (station = ao2_iterator_next(&i));
ao2_ref(station, -1)) {
459 char ring_timeout[16] =
"(none)";
465 snprintf(ring_timeout,
sizeof(ring_timeout),
"%u", station->
ring_timeout);
468 snprintf(ring_delay,
sizeof(ring_delay),
"%u", station->
ring_delay);
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,
484 snprintf(ring_timeout,
sizeof(ring_timeout),
"%u", trunk_ref->
ring_timeout);
486 strcpy(ring_timeout,
"(none)");
489 snprintf(ring_delay,
sizeof(ring_delay),
"%u", trunk_ref->
ring_delay);
491 strcpy(ring_delay,
"(none)");
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);
502 ast_cli(a->fd,
"=== ---------------------------------------------------------\n"
508 ast_cli(a->fd,
"============================================================\n"
515 AST_CLI_DEFINE(sla_show_trunks,
"Show SLA Trunks"),
516 AST_CLI_DEFINE(sla_show_stations,
"Show SLA Stations"),
523 if (
sla.thread == AST_PTHREADT_NULL) {
529 if (!(event =
ast_calloc(1,
sizeof(*event)))) {
536 event->trunk_ref = trunk_ref;
537 event->station = station;
544 ast_mutex_lock(&
sla.lock);
546 ast_cond_signal(&
sla.cond);
547 ast_mutex_unlock(&
sla.lock);
552 sla_queue_event_full(type, NULL, NULL, 0);
557 sla_queue_event_full(type, NULL, NULL, 1);
569 strsep(&trunk_name,
"_");
570 if (ast_strlen_zero(trunk_name)) {
571 ast_log(LOG_ERROR,
"Invalid conference name for SLA - '%s'!\n", confname);
576 while ((station = ao2_iterator_next(&i))) {
579 if (trunk_ref->chan == chan && !strcmp(trunk_ref->trunk->name, trunk_name)) {
594 ast_debug(1,
"Trunk not found for event!\n");
598 sla_queue_event_full(type, trunk_ref, station, 1);
614 static int remove_framehook(
struct ast_channel *chan)
622 ast_log(AST_LOG_WARNING,
"Cannot remove framehook from %s: HOLD_INTERCEPT not currently enabled\n", ast_channel_name(chan));
625 data = datastore->
data;
627 ast_free(data->confname);
630 ast_log(AST_LOG_WARNING,
"Failed to remove framehook from channel %s\n", ast_channel_name(chan));
634 ast_log(AST_LOG_WARNING,
"Failed to remove datastore from channel %s\n", ast_channel_name(chan));
660 static int attach_framehook(
struct ast_channel *chan,
const char *confname)
665 .
version = AST_FRAMEHOOK_INTERFACE_VERSION,
666 .event_cb = sla_framehook,
668 .disable_inheritance = 1,
674 ast_log(AST_LOG_WARNING,
"SLA framehook already set on '%s'\n", ast_channel_name(chan));
678 datastore = ast_datastore_alloc(&sla_framehook_datastore, NULL);
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));
707 static struct sla_trunk *sla_find_trunk(
const char *name)
713 return ao2_find(sla_trunks, &tmp_trunk,
OBJ_POINTER);
720 static struct sla_station *sla_find_station(
const char *name)
726 return ao2_find(sla_stations, &tmp_station,
OBJ_POINTER);
729 static int sla_check_station_hold_access(
const struct sla_trunk *trunk,
const struct sla_station *station)
737 if (trunk_ref->trunk != trunk || station_ref->station == station) {
764 if (strcasecmp(trunk_ref->trunk->name, name)) {
768 if (trunk_ref->trunk->
barge_disabled && trunk_ref->state == SLA_TRUNK_STATE_UP) {
769 ast_debug(2,
"Barge disabled, trunk not available\n");
772 ast_debug(2,
"Private hold by another station\n");
774 }
else if (sla_check_station_hold_access(trunk_ref->trunk, station)) {
789 static void sla_station_ref_destructor(
void *obj)
793 if (station_ref->station) {
794 ao2_ref(station_ref->station, -1);
795 station_ref->station = NULL;
803 if (!(station_ref = ao2_alloc(
sizeof(*station_ref), sla_station_ref_destructor))) {
808 station_ref->station = station;
817 if (!(ringing_station =
ast_calloc(1,
sizeof(*ringing_station)))) {
822 ringing_station->station = station;
825 return ringing_station;
830 if (ringing_station->station) {
831 ao2_ref(ringing_station->station, -1);
832 ringing_station->station = NULL;
835 ast_free(ringing_station);
842 if (!(failed_station =
ast_calloc(1,
sizeof(*failed_station)))) {
847 failed_station->station = station;
850 return failed_station;
855 if (failed_station->station) {
856 ao2_ref(failed_station->station, -1);
857 failed_station->station = NULL;
860 ast_free(failed_station);
863 static enum ast_device_state sla_state_to_devstate(
enum sla_trunk_state state)
866 case SLA_TRUNK_STATE_IDLE:
868 case SLA_TRUNK_STATE_RINGING:
870 case SLA_TRUNK_STATE_UP:
872 case SLA_TRUNK_STATE_ONHOLD:
873 case SLA_TRUNK_STATE_ONHOLD_BYME:
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)
888 while ((station = ao2_iterator_next(&i))) {
891 if (trunk_ref->trunk != trunk || (inactive_only ? trunk_ref->chan : 0) || trunk_ref == exclude) {
894 trunk_ref->state = state;
911 static void answer_trunk_chan(
struct ast_channel *chan)
917 static int conf_run(
struct ast_channel *chan,
const char *confname,
struct ast_flags *confflags,
char *optargs[])
919 char confbridge_args[256];
922 snprintf(confbridge_args,
sizeof(confbridge_args),
"%s", confname);
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]);
934 ast_log(LOG_ERROR,
"Failed to set up conference, aborting\n");
939 if (ast_test_flag(confflags, CONFFLAG_SLA_STATION) && attach_framehook(chan, confname)) {
943 ast_debug(2,
"Channel %s is running ConfBridge(%s)\n", ast_channel_name(chan), confbridge_args);
946 if (ast_test_flag(confflags, CONFFLAG_SLA_STATION)) {
947 remove_framehook(chan);
952 static int conf_kick_all(
struct ast_channel *chan,
const char *confname)
954 char confkick_args[256];
956 snprintf(confkick_args,
sizeof(confkick_args),
"%s,all", confname);
957 ast_debug(2,
"Kicking all participants from conference %s\n", confname);
965 ast_log(LOG_WARNING,
"Failed to allocate dummy channel\n");
975 static void *run_station(
void *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);
993 ast_str_set(&conf_name, 0,
"SLA_%s", trunk_ref->trunk->name);
995 answer_trunk_chan(trunk_ref->chan);
998 conf_run(trunk_ref->chan,
ast_str_buffer(conf_name), &conf_flags, NULL);
1000 trunk_ref->chan = NULL;
1002 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
1005 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
1010 station->dial = NULL;
1011 ast_free(conf_name);
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);
1029 sla_ringing_trunk_destroy(ringing_trunk);
1032 static void sla_stop_ringing_station(
struct sla_ringing_station *ringing_station,
enum sla_station_hangup hangup)
1040 ringing_station->station->dial = NULL;
1042 if (hangup == SLA_STATION_HANGUP_NORMAL) {
1053 if (ringing_trunk->trunk == trunk_ref->trunk) {
1060 if (!(station_ref = sla_create_station_ref(ringing_station->station))) {
1067 sla_ringing_station_destroy(ringing_station);
1070 static void sla_dial_state_callback(
struct ast_dial *dial)
1082 AST_LIST_TRAVERSE(&ringing_trunk->timed_out_stations, timed_out_station, entry) {
1083 if (station == timed_out_station->station) {
1107 if (s_trunk_ref->trunk != ringing_trunk->trunk) {
1123 *trunk_ref = s_trunk_ref;
1130 if (ringing_trunk) {
1135 return ringing_trunk;
1138 static void sla_handle_dial_state_event(
void)
1147 pthread_t dont_care;
1151 switch ((dial_res =
ast_dial_state(ringing_station->station->dial))) {
1158 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_NORMAL);
1163 ast_mutex_lock(&
sla.lock);
1165 ast_mutex_unlock(&
sla.lock);
1166 if (!ringing_trunk) {
1172 ast_debug(1,
"Found no ringing trunk for station '%s' to answer!\n", ringing_station->station->name);
1175 ringing_station->station->dial = NULL;
1176 sla_ringing_station_destroy(ringing_station);
1182 answer_trunk_chan(ringing_trunk->trunk->chan);
1183 sla_change_trunk_state(ringing_trunk->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
1188 args.trunk_ref = s_trunk_ref;
1189 ao2_ref(ringing_station->station, 1);
1190 args.station = ringing_station->station;
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);
1228 if (station == ringing_station->station) {
1245 if (station != failed_station->station) {
1250 sla_failed_station_destroy(failed_station);
1265 char *tech, *tech_data;
1269 int caller_is_saved;
1278 tech = strsep(&tech_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);
1293 res =
ast_dial_run(dial, ringing_trunk->trunk->chan, 1);
1296 if (caller_is_saved) {
1298 ast_channel_caller_set(ringing_trunk->trunk->chan, &caller);
1304 if ((failed_station = sla_create_failed_station(station))) {
1309 if (!(ringing_station = sla_create_ringing_station(station))) {
1315 station->dial = dial;
1329 if (trunk_ref->chan) {
1342 if (trunk_ref->trunk == trunk) {
1360 unsigned int delay = UINT_MAX;
1361 int time_left, time_elapsed;
1363 if (!ringing_trunk) {
1366 trunk_ref = sla_find_trunk_ref(station, ringing_trunk->trunk);
1369 if (!ringing_trunk || !trunk_ref) {
1385 time_left = (delay * 1000) - time_elapsed;
1428 if (time_left != INT_MAX && time_left > 0) {
1439 static void sla_hangup_stations(
void)
1447 ast_mutex_lock(&
sla.lock);
1449 if (trunk_ref->trunk == ringing_trunk->trunk) {
1453 ast_mutex_unlock(&
sla.lock);
1454 if (ringing_trunk) {
1462 ringing_station->station->dial = NULL;
1463 sla_ringing_station_destroy(ringing_station);
1469 static void sla_handle_ringing_trunk_event(
void)
1471 ast_mutex_lock(&
sla.lock);
1473 ast_mutex_unlock(&
sla.lock);
1476 sla_hangup_stations();
1479 static void sla_handle_hold_event(
struct sla_event *event)
1482 event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME;
1484 sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, INACTIVE_TRUNK_REFS, event->trunk_ref);
1489 event->trunk_ref->trunk->on_hold = 1;
1494 event->trunk_ref->chan = NULL;
1507 int time_left, time_elapsed;
1508 if (!ringing_trunk->trunk->ring_timeout) {
1512 time_left = (ringing_trunk->trunk->ring_timeout * 1000) - time_elapsed;
1513 if (time_left <= 0) {
1516 sla_stop_ringing_trunk(ringing_trunk);
1520 if (time_left < *timeout) {
1521 *timeout = time_left;
1540 unsigned int ring_timeout = 0;
1541 int time_elapsed, time_left = INT_MAX, final_trunk_time_left = INT_MIN;
1549 int trunk_time_elapsed, trunk_time_left;
1552 if (ringing_trunk->trunk == trunk_ref->trunk) {
1556 if (!ringing_trunk) {
1570 if (station_ref->station == ringing_station->station) {
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;
1586 if (final_trunk_time_left == INT_MIN && !ringing_station->station->
ring_timeout) {
1594 time_left = (ring_timeout * 1000) - time_elapsed;
1599 if (final_trunk_time_left > INT_MIN && final_trunk_time_left < time_left) {
1600 time_left = final_trunk_time_left;
1604 if (time_left <= 0) {
1606 sla_stop_ringing_station(ringing_station, SLA_STATION_HANGUP_TIMEOUT);
1613 if (time_left < *timeout) {
1614 *timeout = time_left;
1632 for (; (station = ao2_iterator_next(&i));
ao2_ref(station, -1)) {
1658 if (time_left <= 0) {
1663 if (time_left < *timeout) {
1664 *timeout = time_left;
1676 unsigned int timeout = UINT_MAX;
1677 struct timeval wait;
1678 unsigned int change_made = 0;
1701 if (timeout == UINT_MAX) {
1707 ts->tv_sec = wait.tv_sec;
1708 ts->tv_nsec = wait.tv_usec * 1000;
1714 static void sla_event_destroy(
struct sla_event *event)
1716 if (event->trunk_ref) {
1717 ao2_ref(event->trunk_ref, -1);
1718 event->trunk_ref = NULL;
1721 if (event->station) {
1723 event->station = NULL;
1729 static void *sla_thread(
void *data)
1734 ast_mutex_lock(&
sla.lock);
1738 struct timespec ts = { 0, };
1739 unsigned int have_timeout = 0;
1743 ast_cond_timedwait(&
sla.cond, &
sla.lock, &ts);
1745 ast_cond_wait(&
sla.cond, &
sla.lock);
1757 ast_mutex_unlock(&
sla.lock);
1758 switch (event->type) {
1760 sla_handle_hold_event(event);
1763 sla_handle_dial_state_event();
1766 sla_handle_ringing_trunk_event();
1769 sla_event_destroy(event);
1770 ast_mutex_lock(&
sla.lock);
1774 ast_mutex_unlock(&
sla.lock);
1777 sla_ringing_station_destroy(ringing_station);
1781 sla_failed_station_destroy(failed_station);
1794 static void *dial_trunk(
void *data)
1798 char *tech, *tech_data;
1800 char conf_name[MAX_CONFNUM];
1804 int caller_is_saved;
1807 int current_state = 0;
1810 ast_mutex_lock(args->cond_lock);
1811 ast_cond_signal(args->cond);
1812 ast_mutex_unlock(args->cond_lock);
1816 tech_data =
ast_strdupa(trunk_ref->trunk->device);
1817 tech = strsep(&tech_data,
"/");
1819 ast_mutex_lock(args->cond_lock);
1820 ast_cond_signal(args->cond);
1821 ast_mutex_unlock(args->cond_lock);
1827 caller_is_saved = 0;
1828 if (!
sla.attempt_callerid) {
1829 caller_is_saved = 1;
1830 caller = *ast_channel_caller(trunk_ref->chan);
1837 if (caller_is_saved) {
1839 ast_channel_caller_set(trunk_ref->chan, &caller);
1843 ast_mutex_lock(args->cond_lock);
1844 ast_cond_signal(args->cond);
1845 ast_mutex_unlock(args->cond_lock);
1852 unsigned int done = 0;
1856 ast_debug(1,
"Channel %s did not return a frame, must have hung up\n", ast_channel_name(trunk_ref->chan));
1887 ast_debug(3,
"Originating station device %s no longer active\n", station->device);
1888 trunk_ref->trunk->chan = NULL;
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));
1896 last_state = current_state;
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);
1909 snprintf(conf_name,
sizeof(conf_name),
"SLA_%s", trunk_ref->trunk->name);
1912 ast_mutex_lock(args->cond_lock);
1913 ast_cond_signal(args->cond);
1914 ast_mutex_unlock(args->cond_lock);
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);
1920 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
1922 trunk_ref->trunk->chan = NULL;
1923 trunk_ref->trunk->
on_hold = 0;
1940 if (trunk_ref->state == SLA_TRUNK_STATE_IDLE) {
1949 static int sla_station_exec(
struct ast_channel *chan,
const char *data)
1951 char *station_name, *trunk_name;
1954 char conf_name[MAX_CONFNUM];
1957 if (ast_strlen_zero(data)) {
1958 ast_log(LOG_WARNING,
"Invalid Arguments to SLAStation!\n");
1964 station_name = strsep(&trunk_name,
"_");
1966 if (ast_strlen_zero(station_name)) {
1967 ast_log(LOG_WARNING,
"Invalid Arguments to SLAStation!\n");
1972 station = sla_find_station(station_name);
1975 ast_log(LOG_WARNING,
"Station '%s' not found!\n", station_name);
1981 if (!ast_strlen_zero(trunk_name)) {
1986 ao2_unlock(station);
1989 if (ast_strlen_zero(trunk_name)) {
1990 ast_log(LOG_NOTICE,
"No trunks available for call.\n");
1992 ast_log(LOG_NOTICE,
"Can't join existing call on trunk '%s' due to access controls.\n", trunk_name);
1998 if (trunk_ref->state == SLA_TRUNK_STATE_ONHOLD_BYME) {
2000 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
2002 trunk_ref->state = SLA_TRUNK_STATE_UP;
2005 }
else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) {
2008 ast_mutex_lock(&
sla.lock);
2010 if (ringing_trunk->trunk == trunk_ref->trunk) {
2016 ast_mutex_unlock(&
sla.lock);
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);
2022 sla_ringing_trunk_destroy(ringing_trunk);
2030 trunk_ref->chan = chan;
2032 if (!trunk_ref->trunk->chan) {
2035 pthread_t dont_care;
2037 .trunk_ref = trunk_ref,
2039 .cond_lock = &cond_lock,
2044 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
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);
2060 if (!trunk_ref->trunk->chan) {
2061 ast_debug(1,
"Trunk didn't get created. chan: %lx\n", (
unsigned long) trunk_ref->trunk->chan);
2063 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
2064 trunk_ref->chan = NULL;
2071 trunk_ref->trunk->
on_hold = 0;
2073 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL);
2076 snprintf(conf_name,
sizeof(conf_name),
"SLA_%s", trunk_ref->trunk->name);
2080 ast_debug(2,
"Station %s joining conference %s\n", station->name, conf_name);
2081 conf_run(chan, conf_name, &conf_flags, NULL);
2083 trunk_ref->chan = NULL;
2085 trunk_ref->state != SLA_TRUNK_STATE_ONHOLD_BYME) {
2086 conf_kick_all(chan, conf_name);
2088 sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
2096 static void sla_trunk_ref_destructor(
void *obj)
2100 if (trunk_ref->trunk) {
2101 ao2_ref(trunk_ref->trunk, -1);
2102 trunk_ref->trunk = NULL;
2110 if (!(trunk_ref = ao2_alloc(
sizeof(*trunk_ref), sla_trunk_ref_destructor))) {
2115 trunk_ref->trunk = trunk;
2124 if (!(ringing_trunk =
ast_calloc(1,
sizeof(*ringing_trunk)))) {
2129 ringing_trunk->trunk = trunk;
2132 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_RINGING, ALL_TRUNK_REFS, NULL);
2134 ast_mutex_lock(&
sla.lock);
2136 ast_mutex_unlock(&
sla.lock);
2140 return ringing_trunk;
2145 if (ringing_trunk->trunk) {
2146 ao2_ref(ringing_trunk->trunk, -1);
2147 ringing_trunk->trunk = NULL;
2150 ast_free(ringing_trunk);
2153 static int sla_trunk_exec(
struct ast_channel *chan,
const char *data)
2155 char conf_name[MAX_CONFNUM];
2163 char *opts[SLA_TRUNK_OPT_ARG_ARRAY_SIZE] = { NULL, };
2167 if (ast_strlen_zero(data)) {
2168 ast_log(LOG_ERROR,
"The SLATrunk application requires an argument, the trunk name\n");
2174 if (args.argc == 2) {
2176 ast_log(LOG_ERROR,
"Error parsing options for SLATrunk\n");
2181 trunk = sla_find_trunk(args.trunk_name);
2184 ast_log(LOG_ERROR,
"SLA Trunk '%s' not found!\n", args.trunk_name);
2190 ast_log(LOG_ERROR,
"Call came in on %s, but the trunk is already in use!\n", args.trunk_name);
2197 if (!(ringing_trunk = queue_ringing_trunk(trunk))) {
2202 snprintf(conf_name,
sizeof(conf_name),
"SLA_%s", args.trunk_name);
2205 if (ast_test_flag(&opt_flags, SLA_TRUNK_OPT_MOH)) {
2212 ast_debug(2,
"Trunk %s joining conference %s\n", args.trunk_name, conf_name);
2213 conf_run(chan, conf_name, &conf_flags, opts);
2217 sla_change_trunk_state(trunk, SLA_TRUNK_STATE_IDLE, ALL_TRUNK_REFS, NULL);
2224 ast_mutex_lock(&
sla.lock);
2226 if (ringing_trunk->trunk == trunk) {
2232 ast_mutex_unlock(&
sla.lock);
2233 if (ringing_trunk) {
2234 sla_ringing_trunk_destroy(ringing_trunk);
2246 char *buf, *station_name, *trunk_name;
2252 station_name = strsep(&trunk_name,
"_");
2254 station = sla_find_station(station_name);
2258 if (!strcasecmp(trunk_name, trunk_ref->trunk->name)) {
2259 res = sla_state_to_devstate(trunk_ref->state);
2263 ao2_unlock(station);
2267 ast_log(LOG_ERROR,
"Could not determine state for trunk %s on station %s!\n", trunk_name, station_name);
2273 static int sla_trunk_release_refs(
void *obj,
void *arg,
int flags)
2285 static int sla_station_release_refs(
void *obj,
void *arg,
int flags)
2297 static void sla_station_destructor(
void *obj)
2301 ast_debug(1,
"sla_station destructor for '%s'\n", station->name);
2303 if (!ast_strlen_zero(station->autocontext)) {
2309 snprintf(exten,
sizeof(exten),
"%s_%s", station->name, trunk_ref->trunk->name);
2310 snprintf(hint,
sizeof(hint),
"SLA:%s", exten);
2316 sla_station_release_refs(station, NULL, 0);
2321 static int sla_trunk_cmp(
void *obj,
void *arg,
int flags)
2323 struct sla_trunk *trunk = obj, *trunk2 = arg;
2328 static int sla_station_cmp(
void *obj,
void *arg,
int flags)
2330 struct sla_station *station = obj, *station2 = arg;
2335 static void sla_destroy(
void)
2337 if (
sla.thread != AST_PTHREADT_NULL) {
2338 ast_mutex_lock(&
sla.lock);
2340 ast_cond_signal(&
sla.cond);
2341 ast_mutex_unlock(&
sla.lock);
2342 pthread_join(
sla.thread, NULL);
2348 ast_mutex_destroy(&
sla.lock);
2349 ast_cond_destroy(&
sla.cond);
2351 ao2_callback(sla_trunks, 0, sla_trunk_release_refs, NULL);
2352 ao2_callback(sla_stations, 0, sla_station_release_refs, NULL);
2358 sla_stations = NULL;
2361 static int sla_check_device(
const char *device)
2363 char *tech, *tech_data;
2366 tech = strsep(&tech_data,
"/");
2368 if (ast_strlen_zero(tech) || ast_strlen_zero(tech_data)) {
2375 static void sla_trunk_destructor(
void *obj)
2379 ast_debug(1,
"sla_trunk destructor for '%s'\n", trunk->name);
2381 if (!ast_strlen_zero(trunk->autocontext)) {
2385 sla_trunk_release_refs(trunk, NULL, 0);
2390 static int sla_build_trunk(
struct ast_config *cfg,
const char *cat)
2395 int existing_trunk = 0;
2397 if (!(dev = ast_variable_retrieve(cfg, cat,
"device"))) {
2398 ast_log(LOG_ERROR,
"SLA Trunk '%s' defined with no device!\n", cat);
2402 if (sla_check_device(dev)) {
2403 ast_log(LOG_ERROR,
"SLA Trunk '%s' defined with invalid device '%s'!\n", cat, dev);
2407 if ((trunk = sla_find_trunk(cat))) {
2410 }
else if ((trunk = ao2_alloc(
sizeof(*trunk), sla_trunk_destructor))) {
2423 for (var = ast_variable_browse(cfg, cat); var; var = var->
next) {
2424 if (!strcasecmp(var->
name,
"autocontext")) {
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;
2431 }
else if (!strcasecmp(var->
name,
"barge")) {
2433 }
else if (!strcasecmp(var->
name,
"hold")) {
2434 if (!strcasecmp(var->
value,
"private")) {
2436 }
else if (!strcasecmp(var->
value,
"open")) {
2439 ast_log(LOG_WARNING,
"Invalid value '%s' for hold on trunk %s\n", var->
value, trunk->name);
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);
2448 if (!ast_strlen_zero(trunk->autocontext)) {
2450 ast_log(LOG_ERROR,
"Failed to automatically find or create context '%s' for SLA!\n", trunk->autocontext);
2456 ast_log(LOG_ERROR,
"Failed to automatically create extension for trunk '%s'!\n", trunk->name);
2461 if (!existing_trunk) {
2477 char *trunk_name, *options, *cur;
2478 int existing_trunk_ref = 0;
2479 int existing_station_ref = 0;
2482 trunk_name = strsep(&options,
",");
2484 trunk = sla_find_trunk(trunk_name);
2486 ast_log(LOG_ERROR,
"Trunk '%s' not found!\n", var->
value);
2491 if (trunk_ref->trunk == trunk) {
2492 trunk_ref->
mark = 0;
2493 existing_trunk_ref = 1;
2498 if (!trunk_ref && !(trunk_ref = create_trunk_ref(trunk))) {
2502 trunk_ref->state = SLA_TRUNK_STATE_IDLE;
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);
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);
2518 ast_log(LOG_WARNING,
"Invalid option '%s' for trunk '%s' on station '%s'\n", name, trunk->name, station->name);
2523 if (station_ref->station == station) {
2524 station_ref->
mark = 0;
2525 existing_station_ref = 1;
2530 if (!station_ref && !(station_ref = sla_create_station_ref(station))) {
2531 if (!existing_trunk_ref) {
2534 trunk_ref->
mark = 1;
2539 if (!existing_station_ref) {
2546 if (!existing_trunk_ref) {
2549 ao2_unlock(station);
2553 static int sla_build_station(
struct ast_config *cfg,
const char *cat)
2558 int existing_station = 0;
2560 if (!(dev = ast_variable_retrieve(cfg, cat,
"device"))) {
2561 ast_log(LOG_ERROR,
"SLA Station '%s' defined with no device!\n", cat);
2565 if ((station = sla_find_station(cat))) {
2567 existing_station = 1;
2568 }
else if ((station = ao2_alloc(
sizeof(*station), sla_station_destructor))) {
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);
2586 }
else if (!strcasecmp(var->
name,
"autocontext")) {
2588 }
else if (!strcasecmp(var->
name,
"ringtimeout")) {
2590 ast_log(LOG_WARNING,
"Invalid ringtimeout '%s' specified for station '%s'\n", var->
value, station->name);
2593 }
else if (!strcasecmp(var->
name,
"ringdelay")) {
2595 ast_log(LOG_WARNING,
"Invalid ringdelay '%s' specified for station '%s'\n", var->
value, station->name);
2598 }
else if (!strcasecmp(var->
name,
"hold")) {
2599 if (!strcasecmp(var->
value,
"private")) {
2601 }
else if (!strcasecmp(var->
value,
"open")) {
2604 ast_log(LOG_WARNING,
"Invalid value '%s' for hold on station %s\n", var->
value, station->name);
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);
2611 ao2_unlock(station);
2613 if (!ast_strlen_zero(station->autocontext)) {
2617 ast_log(LOG_ERROR,
"Failed to automatically find or create context '%s' for SLA!\n", station->autocontext);
2624 ast_log(LOG_ERROR,
"Failed to automatically create extension for trunk '%s'!\n", station->name);
2630 snprintf(exten,
sizeof(exten),
"%s_%s", station->name, trunk_ref->trunk->name);
2631 snprintf(hint,
sizeof(hint),
"SLA:%s", exten);
2636 ast_log(LOG_ERROR,
"Failed to automatically create extension for trunk '%s'!\n", station->name);
2642 NULL, NULL, hint, NULL, NULL, sla_registrar)) {
2643 ast_log(LOG_ERROR,
"Failed to automatically create hint for trunk '%s'!\n", station->name);
2649 if (!existing_station) {
2656 static int sla_trunk_mark(
void *obj,
void *arg,
int flags)
2666 station_ref->
mark = 1;
2674 static int sla_station_mark(
void *obj,
void *arg,
int flags)
2684 trunk_ref->
mark = 1;
2687 ao2_unlock(station);
2692 static int sla_trunk_is_marked(
void *obj,
void *arg,
int flags)
2700 sla_trunk_release_refs(trunk, NULL, 0);
2706 if (!station_ref->
mark) {
2720 static int sla_station_is_marked(
void *obj,
void *arg,
int flags)
2726 if (station->
mark) {
2728 sla_station_release_refs(station, NULL, 0);
2734 if (!trunk_ref->
mark) {
2743 ao2_unlock(station);
2748 static int sla_in_use(
void)
2753 static int sla_load_config(
int reload)
2757 const char *cat = NULL;
2762 ast_mutex_init(&
sla.lock);
2763 ast_cond_init(&
sla.cond, NULL);
2770 }
else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2772 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
2773 ast_log(LOG_ERROR,
"Config file " SLA_CONFIG_FILE
" is in an invalid format. Aborting.\n");
2782 if ((val = ast_variable_retrieve(cfg,
"general",
"attemptcallerid"))) {
2788 if (!strcasecmp(cat,
"general")) {
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);
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);
2800 ast_log(LOG_WARNING,
"Entry in %s defined with invalid type '%s'!\n", SLA_CONFIG_FILE, type);
2812 if (
sla.thread == AST_PTHREADT_NULL && sla_in_use()) {
2813 ast_pthread_create(&
sla.thread, NULL, sla_thread, NULL);
2819 static int load_config(
int reload)
2821 return sla_load_config(reload);
2824 static int unload_module(
void)
2853 res |= load_config(0);
2864 static int reload(
void)
2866 return load_config(1);
2869 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"Shared Line Appearances",
2870 .support_level = AST_MODULE_SUPPORT_EXTENDED,
2872 .unload = unload_module,
unsigned int active_stations
struct ast_variable * next
static int sla_calc_trunk_timeouts(unsigned int *timeout)
Process trunk ring timeouts.
Main Channel structure associated with a channel.
ast_device_state
Device States.
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
static int sla_check_ringing_station(const struct sla_station *station)
Check to see if this station is already ringing.
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
Main dialing structure. Contains global options, channels being dialed, and more! ...
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
static int load_module(void)
Load the module.
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.
static void hold(struct ast_channel *chan)
Helper method to place a channel in a bridge on hold.
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
#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.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Structure for variables, used for configurations and for channel variables.
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
int ast_devstate_prov_del(const char *label)
Remove device state provider.
A station that is ringing.
Structure for a data store type.
void ast_party_caller_free(struct ast_party_caller *doomed)
Destroy the caller party contents.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
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.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
A reference to a station.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
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.
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.
int ast_unregister_application(const char *app)
Unregister an application.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
void ast_free_ptr(void *ptr)
free() wrapper
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
int ast_raw_answer(struct ast_channel *chan)
Answer a channel.
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.
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
#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.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
ast_dial_result
List of return codes for dial run API calls.
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.
static int sla_calc_station_delays(unsigned int *timeout)
Calculate the ring delay for a station.
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
General Asterisk PBX channel definitions.
struct timeval ring_begin
enum ast_dial_result ast_dial_join(struct ast_dial *dial)
Cancel async thread.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Framehook to support HOLD within the conference.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_dummy_channel_alloc()
Create a fake channel structure.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
#define AST_STRING_FIELD(name)
Declare a string field.
Caller Party information.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
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 ...
int ast_atomic_dec_and_test(volatile int *p)
decrement *p by 1 and return true if the variable has reached 0.
unsigned int barge_disabled
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct timeval ring_begin
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.
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
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.
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).
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.
int ast_pbx_exec_application(struct ast_channel *chan, const char *app_name, const char *app_args)
Execute an application.
unsigned int num_stations
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
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".
Support for dynamic strings.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
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.
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.
struct ast_channel * ast_dial_answered(struct ast_dial *dial)
Return channel that answered.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
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.
#define ast_calloc(num, len)
A wrapper for calloc()
struct ast_dial * ast_dial_create(void)
New dialing structure.
unsigned int hold_stations
Structure used to handle boolean flags.
static int sla_ring_station(struct sla_ringing_trunk *ringing_trunk, struct sla_station *station)
Ring a station.
static struct sla_trunk_ref * sla_choose_idle_trunk(const struct sla_station *station)
For a given station, choose the highest priority idle trunk.
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...
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
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.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
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...
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
A station that failed to be dialed.
int ast_answer(struct ast_channel *chan)
Answer a channel.
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...
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)
static int sla_check_inuse_station(const struct sla_station *station)
Check to see if a station is in use.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
A station's reference to a trunk.
unsigned int ring_timeout
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.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
static int sla_calc_station_timeouts(unsigned int *timeout)
Process station ring timeouts.
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.
static void sla_ring_stations(void)
Ring stations based on current set of ringing trunks.
#define ASTERISK_GPL_KEY
The text the key() function should return.
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.
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.
#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
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.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Structure for mutex and tracking information.
sla_event_type
Event types that can be queued up for the SLA thread.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#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.
#define ao2_link(container, obj)
Add an object to a container.
unsigned int attempt_callerid