72 enum ast_presence_state
state;
75 {
"not_set", AST_PRESENCE_NOT_SET},
76 {
"unavailable", AST_PRESENCE_UNAVAILABLE },
77 {
"available", AST_PRESENCE_AVAILABLE},
78 {
"away", AST_PRESENCE_AWAY},
79 {
"xa", AST_PRESENCE_XA},
80 {
"chat", AST_PRESENCE_CHAT},
81 {
"dnd", AST_PRESENCE_DND},
87 .to_ami = presence_state_to_ami,
122 return AST_PRESENCE_INVALID;
125 static enum ast_presence_state presence_state_cached(
const char *presence_provider,
char **subtype,
char **
message)
127 enum ast_presence_state res = AST_PRESENCE_INVALID;
138 res = presence_state->
state;
140 *subtype = !ast_strlen_zero(presence_state->subtype) ?
ast_strdup(presence_state->subtype) : NULL;
141 *message = !ast_strlen_zero(presence_state->message) ?
ast_strdup(presence_state->message) : NULL;
146 static enum ast_presence_state ast_presence_state_helper(
const char *presence_provider,
char **subtype,
char **message,
int check_cache)
150 enum ast_presence_state
state = AST_PRESENCE_INVALID;
151 enum ast_presence_state state_order[] = {
152 [AST_PRESENCE_INVALID] = 0,
153 [AST_PRESENCE_NOT_SET] = 1,
154 [AST_PRESENCE_AVAILABLE] = 2,
155 [AST_PRESENCE_UNAVAILABLE] = 3,
156 [AST_PRESENCE_CHAT] = 4,
157 [AST_PRESENCE_AWAY] = 5,
158 [AST_PRESENCE_XA] = 6,
159 [AST_PRESENCE_DND] = 7
165 while ((label = strsep(&labels,
"&"))) {
166 enum ast_presence_state next_state = AST_PRESENCE_INVALID;
167 char *next_subtype = NULL;
168 char *next_message = NULL;
171 next_state = presence_state_cached(label, &next_subtype, &next_message);
174 if (next_state == AST_PRESENCE_INVALID) {
179 if ((address = strchr(label,
'/'))) {
183 next_state = chan_tech->
presencestate(address, &next_subtype, &next_message);
185 }
else if ((address = strchr(label,
':'))) {
190 ast_debug(5,
"Checking provider %s with %s\n", provider->label, label);
192 if (!strcasecmp(provider->label, label)) {
193 next_state = provider->callback(address, &next_subtype, &next_message);
200 ast_log(LOG_WARNING,
"No provider found for label: %s\n", label);
203 ast_log(LOG_WARNING,
"No label found for presence state provider: %s\n", label);
207 if (state_order[next_state] > state_order[state]) {
213 *subtype = next_subtype;
214 *message = next_message;
221 enum ast_presence_state
ast_presence_state(
const char *presence_provider,
char **subtype,
char **message)
223 return ast_presence_state_helper(presence_provider, subtype, message, 1);
228 return ast_presence_state_helper(presence_provider, subtype, message, 0);
235 if (!callback || !(provider =
ast_calloc(1,
sizeof(*provider)))) {
239 provider->callback = callback;
255 if (!strcasecmp(provider->label, label)) {
256 AST_RWLIST_REMOVE_CURRENT(list);
262 AST_RWLIST_TRAVERSE_SAFE_END;
268 static void presence_state_dtor(
void *obj)
275 enum ast_presence_state state,
291 return presence_state;
294 static void presence_state_event(
const char *provider,
295 enum ast_presence_state state,
306 presence_state = presence_state_alloc(provider, state, subtype, message);
307 if (!presence_state) {
319 static void do_presence_state_change(
const char *provider)
321 char *subtype = NULL;
322 char *message = NULL;
323 enum ast_presence_state
state;
325 state = ast_presence_state_helper(provider, &subtype, &message, 0);
327 if (state == AST_PRESENCE_INVALID) {
331 presence_state_event(provider, state, subtype, message);
339 const char *presence_provider)
341 if (state == AST_PRESENCE_NOT_SET) {
342 do_presence_state_change(presence_provider);
344 presence_state_event(presence_provider, state, subtype, message);
353 const char *fmt, ...)
359 vsnprintf(buf,
sizeof(buf), fmt, ap);
367 return presence_state_topic_all;
372 return presence_state_cache;
380 static const char *presence_state_get_id(
struct stasis_message *msg)
388 return presence_state->provider;
391 #if defined(TEST_FRAMEWORK)
393 #define TEST_CATEGORY "/main/presence/"
395 static int presence_test_alice_state = AST_PRESENCE_UNAVAILABLE;
396 static int presence_test_bob_state = AST_PRESENCE_UNAVAILABLE;
398 static int presence_test_presencestate(
const char *label,
char **subtype,
char **message)
400 if (!strcmp(label,
"Alice")) {
401 return presence_test_alice_state;
402 }
else if (!strcmp(label,
"Bob")) {
403 return presence_test_bob_state;
405 return AST_PRESENCE_UNAVAILABLE;
410 .type =
"PresenceTestChannel",
411 .description =
"Presence test technology",
412 .presencestate = presence_test_presencestate,
417 int res = AST_TEST_FAIL;
419 enum ast_presence_state state;
420 char *subtype = NULL, *message = NULL;
424 info->name =
"channel_presence";
425 info->category = TEST_CATEGORY;
426 info->summary =
"Channel presence state tests";
427 info->description =
"Creates test channel technology and then test the presence state callback";
428 return AST_TEST_NOT_RUN;
434 ast_log(LOG_WARNING,
"Unable to register channel type '%s'\n", presence_test_tech.type);
435 goto presence_test_cleanup;
439 snprintf(provider,
sizeof(provider),
"%s/Alice", presence_test_tech.type);
441 presence_test_alice_state = AST_PRESENCE_AVAILABLE;
444 if (state != presence_test_alice_state) {
445 ast_log(LOG_WARNING,
"Presence state of '%s' returned '%s' instead of the expected value '%s'\n",
447 goto presence_test_cleanup;
451 snprintf(provider,
sizeof(provider),
"%s/Alice&%s/Bob", presence_test_tech.type, presence_test_tech.type);
453 presence_test_alice_state = AST_PRESENCE_DND;
454 presence_test_bob_state = AST_PRESENCE_UNAVAILABLE;
457 if (state != presence_test_alice_state) {
458 ast_log(LOG_WARNING,
"Presence state of '%s' returned '%s' instead of the expected value '%s'\n",
460 goto presence_test_cleanup;
464 presence_test_alice_state = AST_PRESENCE_AVAILABLE;
467 if (state != presence_test_bob_state) {
468 ast_log(LOG_WARNING,
"Presence state of '%s' returned '%s' instead of the expected value '%s'\n",
470 goto presence_test_cleanup;
475 presence_test_cleanup:
484 static void presence_state_engine_cleanup(
void)
486 ao2_cleanup(presence_state_topic_all);
487 presence_state_topic_all = NULL;
488 ao2_cleanup(presence_state_cache);
489 presence_state_cache = NULL;
492 AST_TEST_UNREGISTER(test_presence_chan);
495 int ast_presence_state_engine_init(
void)
504 if (!presence_state_topic_all) {
509 if (!presence_state_cache) {
514 if (!presence_state_topic_cached) {
520 AST_TEST_REGISTER(test_presence_chan);
538 presence_state->provider,
int(*const presencestate)(const char *presence_provider, char **subtype, char **message)
Struct containing info for an AMI event to send out.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int stasis_caching_accept_message_type(struct stasis_caching_topic *caching_topic, struct stasis_message_type *type)
Indicate to a caching topic that we are interested in a message type.
int ast_presence_state_prov_del(const char *label)
Remove presence state provider.
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
A presence state provider.
struct stasis_caching_topic * stasis_caching_topic_create(struct stasis_topic *original_topic, struct stasis_cache *cache)
Create a topic which monitors and caches messages from another topic.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
static struct ast_sockaddr address
Address for UDPTL.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Stasis message payload representing a presence state update.
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 ...
#define ast_strdup(str)
A wrapper for strdup()
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.
struct stasis_caching_topic * stasis_caching_unsubscribe_and_join(struct stasis_caching_topic *caching_topic)
Unsubscribes a caching topic from its upstream topic, blocking until all messages have been forwarded...
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
enum ast_presence_state ast_presence_state(const char *presence_provider, char **subtype, char **message)
Asks a presence state provider for the current presence state.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
int ast_presence_state_changed(enum ast_presence_state state, const char *subtype, const char *message, const char *fmt,...)
Notify the world that a presence provider state changed.
enum ast_presence_state ast_presence_state_nocache(const char *presence_provider, char **subtype, char **message)
Asks a presence state provider for the current presence state, bypassing the event cache...
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
#define STASIS_MESSAGE_TYPE_DEFN(name,...)
Boiler-plate messaging macro for defining public message types.
Presence state management.
int stasis_caching_set_filter(struct stasis_caching_topic *caching_topic, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a cache.
static const struct @386 state2string[]
Device state strings for printing.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
#define ast_calloc(num, len)
A wrapper for calloc()
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
Prototypes for public functions only of internal interest,.
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
struct stasis_cache * stasis_cache_create(snapshot_get_id id_fn)
Create a cache.
struct stasis_cache * ast_presence_state_cache(void)
Backend cache for ast_presence_state_topic_cached()
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
enum ast_presence_state state
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
#define AST_TEST_DEFINE(hdr)
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
int ast_presence_state_changed_literal(enum ast_presence_state state, const char *subtype, const char *message, const char *presence_provider)
Notify the world that a presence provider state changed.
struct stasis_topic * ast_presence_state_topic_cached(void)
Get caching presence state topic.
int ast_presence_state_prov_add(const char *label, ast_presence_state_prov_cb_type callback)
Add presence state provider.
enum ast_presence_state ast_presence_state_val(const char *val)
Convert presence state from text to integer value.
struct stasis_topic * stasis_caching_get_topic(struct stasis_caching_topic *caching_topic)
Returns the topic of cached events from a caching topics.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#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...
enum ast_presence_state(* ast_presence_state_prov_cb_type)(const char *data, char **subtype, char **message)
Presence state provider call back.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.