Asterisk - The Open Source Telephony Project GIT-master-a358458
test_devicestate.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2010, Digium, Inc.
5 *
6 * David Vossel <dvossel@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief Device State Test Module
22 *
23 * \author David Vossel <dvossel@digium.com>
24 *
25 * \ingroup tests
26 */
27
28/*** MODULEINFO
29 <depend>TEST_FRAMEWORK</depend>
30 <support_level>core</support_level>
31 ***/
32
33#include "asterisk.h"
34
35#include "asterisk/utils.h"
36#include "asterisk/module.h"
37#include "asterisk/test.h"
39#include "asterisk/pbx.h"
41#include "asterisk/vector.h"
42
43#define UNIT_TEST_DEVICE_IDENTIFIER "unit_test_device_identifier"
44
45#define DEVICE_STATE_CHANNEL_TYPE "TestDeviceState"
46
47#define DEVSTATE_PROVIDER "TestDevState"
48
49#define DEVSTATE_PROVIDER_LC "testdevstate"
50
51#define DEVSTATE_PROVIDER_LEN 12
52
53/*! \brief Used to assign an increasing integer to channel name */
54static unsigned int chan_idx;
55
56/* These arrays are the result of the 'core show device2extenstate' output. */
57static int combined_results[] = {
139};
140
141static int exten_results[] = {
223};
224
225/*! \brief Mutex for \c update_cond */
227
228/*! \brief Condition wait variable for device state updates */
230
231/*! \brief Mutext for \c channel_cb_cond */
233
234/*! \brief Condition wait variable for channel tech device state cb */
236
237/*! \brief The resulting device state updates caused by some function call */
239
240/*! \brief The current device state for our device state provider */
242
243/*! \brief Clear out all recorded device states in \p result_states */
244static void clear_result_states(void)
245{
247 while (AST_VECTOR_SIZE(&result_states) > 0) {
249 }
251}
252
253/*! \brief Stasis subscription callback for device state updates */
254static void device_state_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
255{
256 struct ast_device_state_message *payload;
258 const char *device;
259
261 return;
262 }
263
264 payload = stasis_message_data(message);
265 state = payload->state;
266 device = payload->device;
267
268 if (ast_strlen_zero(device)) {
269 return;
270 }
271
272 /* Ignore aggregate events */
273 if (!payload->eid) {
274 return;
275 }
276
278 return;
279 }
280
285}
286
287static enum ast_device_state devstate_prov_cb(const char *data)
288{
290}
291
292static int wait_for_device_state_updates(struct ast_test *test, int expected_updates)
293{
294 int error;
295 struct timeval wait_now = ast_tvnow();
296 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };
297
299 while (AST_VECTOR_SIZE(&result_states) != expected_updates) {
301 if (error == ETIMEDOUT) {
302 ast_test_status_update(test, "Test timed out while waiting for %d expected updates\n", expected_updates);
303 break;
304 }
305 }
307
308 ast_test_status_update(test, "Received %zu of %d updates\n", AST_VECTOR_SIZE(&result_states), expected_updates);
309 return !(AST_VECTOR_SIZE(&result_states) == expected_updates);
310}
311
312AST_TEST_DEFINE(device2extenstate_test)
313{
314 int res = AST_TEST_PASS;
315 struct ast_devstate_aggregate agg;
316 enum ast_device_state i, j, combined;
317 enum ast_extension_states exten;
318 int k = 0;
319
320 switch (cmd) {
321 case TEST_INIT:
322 info->name = "device2extenstate_test";
323 info->category = "/main/devicestate/";
324 info->summary = "Tests combined devstate mapping and device to extension state mapping.";
325 info->description =
326 "Verifies device state aggregate results match the expected combined "
327 "devstate. Then verifies the combined devstate maps to the expected "
328 "extension state.";
329 return AST_TEST_NOT_RUN;
330 case TEST_EXECUTE:
331 break;
332 }
333
335 ast_test_status_update(test, "Result array is %d long when it should be %d. "
336 "Something has changed, this test must be updated.\n",
338 return AST_TEST_FAIL;
339 }
340
342 ast_test_status_update(test, "combined_results and exten_results arrays do not match in length.\n");
343 return AST_TEST_FAIL;
344 }
345
346 for (i = 0; i < AST_DEVICE_TOTAL; i++) {
347 for (j = 0; j < AST_DEVICE_TOTAL; j++) {
351 combined = ast_devstate_aggregate_result(&agg);
352 if (combined_results[k] != combined) {
353 ast_test_status_update(test, "Expected combined dev state %s "
354 "does not match %s at combined_result[%d].\n",
356 ast_devstate2str(combined), k);
357 res = AST_TEST_FAIL;
358 }
359
360 exten = ast_devstate_to_extenstate(combined);
361
362 if (exten_results[k] != exten) {
363 ast_test_status_update(test, "Expected exten state %s "
364 "does not match %s at exten_result[%d]\n",
366 ast_extension_state2str(exten), k);
367 res = AST_TEST_FAIL;
368 }
369 k++;
370 }
371 }
372
373 return res;
374}
375
376struct consumer {
383};
384
385static void consumer_dtor(void *obj)
386{
387 struct consumer *consumer = obj;
388
390}
391
392static void consumer_reset(struct consumer *consumer)
393{
398}
399
400static struct consumer *consumer_create(void)
401{
402 struct consumer *consumer;
403
405 if (!consumer) {
406 return NULL;
407 }
408
411
412 return consumer;
413}
414
415static void consumer_exec(void *data, struct stasis_subscription *sub, struct stasis_message *message)
416{
417 struct consumer *consumer = data;
419 struct ast_device_state_message *device_state;
420
421 if (!cache_update->new_snapshot) {
422 return;
423 }
424
425 device_state = stasis_message_data(cache_update->new_snapshot);
426
427 if (strcmp(device_state->device, UNIT_TEST_DEVICE_IDENTIFIER)) {
428 /* not a device state we're interested in */
429 return;
430 }
431
432 {
434
436 if (device_state->eid) {
437 consumer->state = device_state->state;
442 }
443 } else {
444 consumer->aggregate_state = device_state->state;
447 }
448 }
449}
450
451static void consumer_finalize(void *data, struct stasis_subscription *sub, struct stasis_message *message)
452{
453 struct consumer *consumer = data;
454
457 }
458}
459
461{
462 int res;
463 struct timeval start = ast_tvnow();
464 struct timespec end = {
465 .tv_sec = start.tv_sec + 10,
466 .tv_nsec = start.tv_usec * 1000
467 };
468
470
471 while (!consumer->already_out) {
473 if (!res || res == ETIMEDOUT) {
474 break;
475 }
476 }
477}
478
479static int remove_device_states_cb(void *obj, void *arg, int flags)
480{
481 struct stasis_message *msg = obj;
482 struct ast_device_state_message *device_state = stasis_message_data(msg);
483
484 if (strcmp(UNIT_TEST_DEVICE_IDENTIFIER, device_state->device)) {
485 /* Not a unit test device */
486 return 0;
487 }
488
489 msg = stasis_cache_clear_create(msg);
490 if (msg) {
491 /* topic guaranteed to have been created by this point */
492 stasis_publish(ast_device_state_topic(device_state->device), msg);
493 }
494 ao2_cleanup(msg);
495 return 0;
496}
497
498static void cache_cleanup(int unused)
499{
500 struct ao2_container *cache_dump;
501
502 /* remove all device states created during this test */
504 if (!cache_dump) {
505 return;
506 }
508 ao2_cleanup(cache_dump);
509}
510
511AST_TEST_DEFINE(device_state_aggregation_test)
512{
515 RAII_VAR(struct ast_eid *, foreign_eid, NULL, ast_free);
516 RAII_VAR(int, cleanup_cache, 0, cache_cleanup);
517 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
518 int res;
519 struct ast_device_state_message *device_state;
520
521 switch (cmd) {
522 case TEST_INIT:
523 info->name = "device_state_aggregation_test";
524 info->category = "/main/devicestate/";
525 info->summary = "Tests message routing and aggregation through the Stasis device state system.";
526 info->description =
527 "Verifies that the device state system passes "
528 "messages appropriately, that the aggregator is "
529 "working properly, that the aggregate results match "
530 "the expected combined devstate, and that the cached "
531 "aggregate devstate is correct.";
532 return AST_TEST_NOT_RUN;
533 case TEST_EXECUTE:
534 break;
535 }
536
537 foreign_eid = ast_malloc(sizeof(*foreign_eid));
538 ast_test_validate(test, NULL != foreign_eid);
539 memset(foreign_eid, 0xFF, sizeof(*foreign_eid));
540
542 ast_test_validate(test, NULL != consumer);
543
545 ast_test_validate(test, NULL != device_msg_router);
546
547 ao2_ref(consumer, +1);
549 ast_test_validate(test, !res);
550
552 ast_test_validate(test, !res);
553
554 /* push local state */
556
557 /* Check cache aggregate state immediately */
558 ao2_cleanup(msg);
560 device_state = stasis_message_data(msg);
561 ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
562
564 ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
565 ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->aggregate_state);
566 ast_test_validate(test, 2 == consumer->event_count);
568
569 /* push remote state */
570 /* this will not produce a new aggregate state message since the aggregate state does not change */
573
574 /* Check cache aggregate state immediately */
575 ao2_cleanup(msg);
577 device_state = stasis_message_data(msg);
578 ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
579
580 /* Check for expected events. */
582 ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
583 ast_test_validate(test, AST_DEVICE_TOTAL == consumer->aggregate_state);
584 ast_test_validate(test, 1 == consumer->event_count);
586
587 /* push remote state different from local state */
589
590 /* Check cache aggregate state immediately */
591 ao2_cleanup(msg);
593 device_state = stasis_message_data(msg);
594 ast_test_validate(test, AST_DEVICE_INUSE == device_state->state);
595
596 /* Check for expected events. */
598 ast_test_validate(test, AST_DEVICE_INUSE == consumer->state);
599 ast_test_validate(test, AST_DEVICE_INUSE == consumer->aggregate_state);
600 ast_test_validate(test, 2 == consumer->event_count);
602
603 /* push local state that will cause aggregated state different from local non-aggregate state */
605
606 /* Check cache aggregate state immediately */
607 ao2_cleanup(msg);
609 device_state = stasis_message_data(msg);
610 ast_test_validate(test, AST_DEVICE_RINGINUSE == device_state->state);
611
612 /* Check for expected events. */
614 ast_test_validate(test, AST_DEVICE_RINGING == consumer->state);
615 ast_test_validate(test, AST_DEVICE_RINGINUSE == consumer->aggregate_state);
616 ast_test_validate(test, 2 == consumer->event_count);
618
619 return AST_TEST_PASS;
620}
621
622AST_TEST_DEFINE(devstate_prov_add)
623{
624 switch (cmd) {
625 case TEST_INIT:
626 info->name = __func__;
627 info->category = "/main/devicestate/";
628 info->summary = "Test adding a device state provider";
629 info->description =
630 "Test that a custom device state provider can be added, and that\n"
631 "it cannot be added if already added.";
632 return AST_TEST_NOT_RUN;
633 case TEST_EXECUTE:
634 break;
635 }
636
639 ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
640
641 return AST_TEST_PASS;
642}
643
644AST_TEST_DEFINE(devstate_prov_del)
645{
646 switch (cmd) {
647 case TEST_INIT:
648 info->name = __func__;
649 info->category = "/main/devicestate/";
650 info->summary = "Test removing a device state provider";
651 info->description =
652 "Test that a custom device state provider can be removed, and that\n"
653 "it cannot be removed if already removed.";
654 return AST_TEST_NOT_RUN;
655 case TEST_EXECUTE:
656 break;
657 }
658
660 ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
661 ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) != 0);
662
663 return AST_TEST_PASS;
664}
665
666AST_TEST_DEFINE(devstate_changed)
667{
669 int i;
670 enum ast_device_state expected_results[] = {
679 };
680
681 switch (cmd) {
682 case TEST_INIT:
683 info->name = __func__;
684 info->category = "/main/devicestate/";
685 info->summary = "Test updates coming from a device state provider";
686 info->description =
687 "This unit test checks that a custom device state provider can\n"
688 "have updates published for it. This includes both cacheable and\n"
689 "non-cacheable events. In the case of non-cacheable events, the\n"
690 "device state provider's callback function is queried for the\n"
691 "device state when AST_DEVICE_UNKNOWN is published.";
692 return AST_TEST_NOT_RUN;
693 case TEST_EXECUTE:
694 break;
695 }
696
698
701
703
712
713 ast_test_validate(test, wait_for_device_state_updates(test, 8) == 0);
714
715 for (i = 0; i < AST_VECTOR_SIZE(&result_states); i++) {
716 ast_test_status_update(test, "Testing update %d: actual is %d; expected is %d\n",
717 i,
719 expected_results[i]);
720 ast_test_validate(test, AST_VECTOR_GET(&result_states, i) == expected_results[i]);
721 }
722
725
726 /*
727 * Since an update of AST_DEVICE_UNKNOWN will cause a different thread to retrieve
728 * the update from the custom device state provider, check it separately from the
729 * updates above.
730 */
733 ast_test_validate(test, wait_for_device_state_updates(test, 1) == 0);
734
735 ast_test_validate(test, AST_VECTOR_GET(&result_states, 0) == AST_DEVICE_BUSY);
736 ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER ":foo") == AST_DEVICE_BUSY);
737 ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER_LC ":foo") == AST_DEVICE_BUSY);
738
741
751
752 ast_test_validate(test, wait_for_device_state_updates(test, 8) == 0);
753 for (i = 0; i < AST_VECTOR_SIZE(&result_states); i++) {
754 ast_test_status_update(test, "Testing update %d: actual is %d; expected is %d\n",
755 i,
757 expected_results[i]);
758 ast_test_validate(test, AST_VECTOR_GET(&result_states, i) == expected_results[i]);
759 }
760
761 /*
762 * Check the last value in the cache. Note that this should not hit
763 * the value of current_device_state.
764 */
765 ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER ":foo") == AST_DEVICE_ONHOLD);
766 /*
767 * This will miss on the cache, as it is case sensitive. It should go
768 * hit our device state callback however.
769 */
770 ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER_LC ":foo") == AST_DEVICE_BUSY);
771
772 /* Generally, this test can't be run twice in a row, as you can't remove an
773 * item from the cache. Hence, subsequent runs won't hit the device state provider,
774 * and will merely return the cached value.
775 *
776 * To avoid annoying errors, set the last state to BUSY here.
777 */
779
780 ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
781
784
785 return AST_TEST_PASS;
786}
787
788AST_TEST_DEFINE(devstate_conversions)
789{
790 switch (cmd) {
791 case TEST_INIT:
792 info->name = __func__;
793 info->category = "/main/devicestate/";
794 info->summary = "Test ast_device_state conversions";
795 info->description =
796 "Test various transformations of ast_device_state values.";
797 return AST_TEST_NOT_RUN;
798 case TEST_EXECUTE:
799 break;
800 }
801
802 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_UNKNOWN), "UNKNOWN"));
803 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_NOT_INUSE), "NOT_INUSE"));
804 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_INUSE), "INUSE"));
805 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_BUSY), "BUSY"));
806 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_INVALID), "INVALID"));
807 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_UNAVAILABLE), "UNAVAILABLE"));
808 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_RINGING), "RINGING"));
809 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_RINGINUSE), "RINGINUSE"));
810 ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_ONHOLD), "ONHOLD"));
811
812 ast_test_validate(test, ast_devstate_val("UNKNOWN") == AST_DEVICE_UNKNOWN);
813 ast_test_validate(test, ast_devstate_val("NOT_INUSE") == AST_DEVICE_NOT_INUSE);
814 ast_test_validate(test, ast_devstate_val("INUSE") == AST_DEVICE_INUSE);
815 ast_test_validate(test, ast_devstate_val("BUSY") == AST_DEVICE_BUSY);
816 ast_test_validate(test, ast_devstate_val("INVALID") == AST_DEVICE_INVALID);
817 ast_test_validate(test, ast_devstate_val("UNAVAILABLE") == AST_DEVICE_UNAVAILABLE);
818 ast_test_validate(test, ast_devstate_val("RINGING") == AST_DEVICE_RINGING);
819 ast_test_validate(test, ast_devstate_val("RINGINUSE") == AST_DEVICE_RINGINUSE);
820 ast_test_validate(test, ast_devstate_val("ONHOLD") == AST_DEVICE_ONHOLD);
821 ast_test_validate(test, ast_devstate_val("onhold") == AST_DEVICE_ONHOLD);
822 ast_test_validate(test, ast_devstate_val("FOO") == AST_DEVICE_UNKNOWN);
823
834
835 return AST_TEST_PASS;
836}
837
838/*! \brief Whether or not the channel device state callback was called */
840
841/*! \brief Wait until the test channel driver's devicestate callback is called */
842static int wait_for_channel_callback(struct ast_test *test)
843{
844 int error;
845 struct timeval wait_now = ast_tvnow();
846 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };
847
849 while (!chan_callback_called) {
851 if (error == ETIMEDOUT) {
852 ast_test_status_update(test, "Test timed out while waiting channel callback\n");
853 break;
854 }
855 }
857
859}
860
861static void safe_hangup(void *object)
862{
863 struct ast_channel *chan = object;
864
865 if (!chan) {
866 return;
867 }
868 ast_hangup(chan);
869}
870
871AST_TEST_DEFINE(devstate_channels)
872{
873 RAII_VAR(struct ast_channel *, chan, NULL, safe_hangup);
874
875 switch (cmd) {
876 case TEST_INIT:
877 info->name = __func__;
878 info->category = "/main/devicestate/";
879 info->summary = "Test deriving device state from a channel's state";
880 info->description =
881 "Test querying a channel's state to derive a device state.";
882 return AST_TEST_NOT_RUN;
883 case TEST_EXECUTE:
884 break;
885 }
886
888
889 chan = ast_channel_alloc(0, AST_STATE_RINGING, "", "", "", "s", "default",
890 NULL, NULL, 0, DEVICE_STATE_CHANNEL_TYPE "/foo-%08x",
891 (unsigned) ast_atomic_fetchadd_int((int *) &chan_idx, +1));
892 ast_test_validate(test, chan != NULL);
893
896
898
899 ast_test_validate(test, wait_for_channel_callback(test) == 1);
901
903
904 return AST_TEST_PASS;
905}
906
907static int chan_test_devicestate_cb(const char *device_number)
908{
909 /* Simply record that we were called when expected */
911
915
916 return AST_DEVICE_INUSE;
917}
918
921 .description = "Device State Unit Test Channel Driver",
922 .devicestate = chan_test_devicestate_cb,
923};
924
925static int unload_module(void)
926{
929
930 AST_TEST_UNREGISTER(device2extenstate_test);
931 AST_TEST_UNREGISTER(device_state_aggregation_test);
932
933 AST_TEST_UNREGISTER(devstate_prov_add);
934 AST_TEST_UNREGISTER(devstate_prov_del);
935
936 AST_TEST_UNREGISTER(devstate_changed);
937 AST_TEST_UNREGISTER(devstate_conversions);
938
939 AST_TEST_UNREGISTER(devstate_channels);
940
941 return 0;
942}
943
944static int load_module(void)
945{
946 if (AST_VECTOR_INIT(&result_states, 8) == -1) {
948 }
949
953 }
954
955 AST_TEST_REGISTER(device_state_aggregation_test);
956 AST_TEST_REGISTER(device2extenstate_test);
957
958 AST_TEST_REGISTER(devstate_prov_add);
959 AST_TEST_REGISTER(devstate_prov_del);
960
961 AST_TEST_REGISTER(devstate_changed);
962 AST_TEST_REGISTER(devstate_conversions);
963
964 AST_TEST_REGISTER(devstate_channels);
965
967}
968
ast_mutex_t lock
Definition: app_sla.c:331
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
enum cc_state state
Definition: ccss.c:393
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DIALING_OFFHOOK
Definition: channelstate.h:44
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_PRERING
Definition: channelstate.h:45
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_OFFHOOK
Definition: channelstate.h:38
@ AST_STATE_BUSY
Definition: channelstate.h:43
@ AST_STATE_DIALING
Definition: channelstate.h:39
@ AST_STATE_UP
Definition: channelstate.h:42
@ AST_STATE_RESERVED
Definition: channelstate.h:37
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
Device state management.
#define ast_publish_device_state(device, state, cachable)
Publish a device state update.
Definition: devicestate.h:321
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:636
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
struct stasis_topic * ast_device_state_topic_cached(void)
Get the Stasis caching topic for device state messages.
Definition: devicestate.c:678
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663
enum ast_device_state ast_state_chan2dev(enum ast_channel_state chanstate)
Convert channel state to devicestate.
Definition: devicestate.c:242
enum ast_device_state ast_parse_device_state(const char *device)
Search the Channels by Name.
Definition: devicestate.c:287
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:471
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:260
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_RINGINUSE
Definition: devicestate.h:60
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53
@ AST_DEVICE_ONHOLD
Definition: devicestate.h:61
@ AST_DEVICE_RINGING
Definition: devicestate.h:59
@ AST_DEVICE_INVALID
Definition: devicestate.h:57
@ AST_DEVICE_BUSY
Definition: devicestate.h:56
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
@ AST_DEVICE_TOTAL
Definition: devicestate.h:62
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
Definition: devicestate.c:709
char * end
Definition: eagi_proxy.c:73
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
struct stasis_message_type * stasis_cache_update_type(void)
Message type for cache update messages.
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_unlock(a)
Definition: lock.h:190
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
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define ast_cond_signal(cond)
Definition: lock.h:203
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
def info(msg)
Core PBX routines and definitions.
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
Definition: pbx.c:3126
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:3006
ast_extension_states
Extension states.
Definition: pbx.h:61
@ AST_EXTENSION_RINGING
Definition: pbx.h:68
@ AST_EXTENSION_NOT_INUSE
Definition: pbx.h:64
@ AST_EXTENSION_INUSE
Definition: pbx.h:65
@ AST_EXTENSION_UNAVAILABLE
Definition: pbx.h:67
@ AST_EXTENSION_ONHOLD
Definition: pbx.h:69
@ AST_EXTENSION_BUSY
Definition: pbx.h:66
struct stasis_forward * sub
Definition: res_corosync.c:240
#define NULL
Definition: resample.c:96
struct stasis_message * stasis_cache_clear_create(struct stasis_message *message)
A message which instructs the caching topic to remove an entry from its cache.
Definition: stasis_cache.c:778
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
struct ao2_container * stasis_cache_dump_all(struct stasis_cache *cache, struct stasis_message_type *type)
Dump all entity items from the cache to a subscription.
Definition: stasis_cache.c:757
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition: stasis.c:1174
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1134
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
struct stasis_message * stasis_cache_get_by_eid(struct stasis_cache *cache, struct stasis_message_type *type, const char *id, const struct ast_eid *eid)
Retrieve an item from the cache for a specific entity.
Definition: stasis_cache.c:659
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649
static struct stasis_message * cache_update(struct stasis_cache_entry *cached_entry, const struct ast_eid *eid, struct stasis_message *new_snapshot)
Definition: stasis_cache.c:466
#define stasis_message_router_create(topic)
Create a new message router object.
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Generic container type.
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
const char *const type
Definition: channel.h:629
Main Channel structure associated with a channel.
The structure that contains device state.
Definition: devicestate.h:238
enum ast_device_state state
Definition: devicestate.h:248
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246
You shouldn't care about the contents of this struct.
Definition: devicestate.h:228
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:813
enum ast_device_state state
enum ast_device_state aggregate_state
ast_cond_t out
int sig_on_non_aggregate_state
Cache update message.
Definition: stasis.h:965
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static ast_cond_t update_cond
Condition wait variable for device state updates.
static void consumer_reset(struct consumer *consumer)
static void safe_hangup(void *object)
struct ast_channel_tech chan_test_devicestate
static void consumer_exec(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define DEVSTATE_PROVIDER
static int combined_results[]
static ast_cond_t channel_cb_cond
Condition wait variable for channel tech device state cb.
static enum ast_device_state current_device_state
The current device state for our device state provider.
AST_TEST_DEFINE(device2extenstate_test)
static enum ast_device_state devstate_prov_cb(const char *data)
static void consumer_dtor(void *obj)
#define DEVICE_STATE_CHANNEL_TYPE
static int chan_test_devicestate_cb(const char *device_number)
static void cache_cleanup(int unused)
static ast_mutex_t channel_cb_lock
Mutext for channel_cb_cond.
static struct @496 result_states
The resulting device state updates caused by some function call.
#define DEVSTATE_PROVIDER_LC
static int wait_for_device_state_updates(struct ast_test *test, int expected_updates)
static void consumer_finalize(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define DEVSTATE_PROVIDER_LEN
static struct consumer * consumer_create(void)
static int chan_callback_called
Whether or not the channel device state callback was called.
static int exten_results[]
static void consumer_wait_for(struct consumer *consumer)
static int remove_device_states_cb(void *obj, void *arg, int flags)
#define UNIT_TEST_DEVICE_IDENTIFIER
static int load_module(void)
static int unload_module(void)
static unsigned int chan_idx
Used to assign an increasing integer to channel name.
static int wait_for_channel_callback(struct ast_test *test)
Wait until the test channel driver's devicestate callback is called.
static void clear_result_states(void)
Clear out all recorded device states in result_states.
static ast_mutex_t update_lock
Mutex for update_cond.
static void device_state_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback for device state updates.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int error(const char *format,...)
Definition: utils/frame.c:999
Utility functions.
#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
#define ARRAY_LEN(a)
Definition: utils.h:666
Vector container support.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680