109 char *subtype =
NULL;
111 int base64encode = 0;
128 ast_log(
LOG_WARNING,
"PRESENCE_STATE reading requires both presence provider and presence field arguments. \n");
155 }
else if (!strcasecmp(
args.field,
"value")) {
174 state_str =
strsep(&data,
",");
187 if (!(*subtype =
strsep(&data,
","))) {
212 size_t len = strlen(
"CustomPresence:");
218 if (strncasecmp(data,
"CustomPresence:",
len)) {
219 ast_log(
LOG_WARNING,
"The PRESENCE_STATE function can only set CustomPresence: presence providers.\n");
237 char decoded_subtype[256] = { 0, };
238 char decoded_message[256] = { 0, };
240 ast_base64decode((
unsigned char *) decoded_subtype, subtype,
sizeof(decoded_subtype) -1);
267 if ((strchr(_options,
'e'))) {
273 memset(tmp, 0,
sizeof(tmp));
281 memset(tmp, 0,
sizeof(tmp));
293 .
name =
"PRESENCE_STATE",
304 e->
command =
"presencestate list";
306 "Usage: presencestate list\n"
307 " List all custom presence states that have been set by using\n"
308 " the PRESENCE_STATE dialplan function.\n";
314 if (
a->argc != e->
args) {
319 "---------------------------------------------------------------------\n"
320 "--- Custom Presence States ------------------------------------------\n"
321 "---------------------------------------------------------------------\n"
326 ast_cli(
a->fd,
"No custom presence states defined\n");
329 for (; db_entry; db_entry = db_entry->
next) {
330 const char *object_name = strrchr(db_entry->
key,
'/') + 1;
331 char state_info[1301];
343 if (object_name <= (
const char *) 1) {
346 ast_cli(
a->fd,
"--- Name: 'CustomPresence:%s'\n"
348 " --- Subtype: '%s'\n"
349 " --- Message: '%s'\n"
350 " --- Base64 Encoded: '%s'\n"
362 "---------------------------------------------------------------------\n"
363 "---------------------------------------------------------------------\n"
372 const char *dev, *
state, *full_dev;
381 e->
command =
"presencestate change";
383 "Usage: presencestate change <entity> <state>[,<subtype>[,message[,options]]]\n"
384 " Change a custom presence to a new state.\n"
385 " The possible values for the state are:\n"
386 "NOT_SET | UNAVAILABLE | AVAILABLE | AWAY | XA | CHAT | DND\n"
387 "Optionally, a custom subtype and message may be provided, along with any options\n"
388 "accepted by func_presencestate. If the subtype or message provided contain spaces,\n"
389 "be sure to enclose the data in quotation marks (\"\")\n"
392 " presencestate change CustomPresence:mystate1 AWAY\n"
393 " presencestate change CustomPresence:mystate1 AVAILABLE\n"
394 " presencestate change CustomPresence:mystate1 \"Away,upstairs,eating lunch\"\n"
399 static const char *
const cmds[] = {
"NOT_SET",
"UNAVAILABLE",
"AVAILABLE",
"AWAY",
400 "XA",
"CHAT",
"DND",
NULL };
402 if (
a->pos == e->
args + 1) {
410 if (
a->argc != e->
args + 2) {
414 len = strlen(
"CustomPresence:");
415 full_dev = dev =
a->argv[e->
args];
418 if (strncasecmp(dev,
"CustomPresence:",
len)) {
419 ast_cli(
a->fd,
"The presencestate command can only be used to set 'CustomPresence:' presence state!\n");
472 struct test_string tests [] = {
522 {
"away,down the hall",
529 {
"away,down the hall,Quarterly financial meeting",
532 "Quarterly financial meeting",
536 {
"away,,Quarterly financial meeting",
539 "Quarterly financial meeting",
550 {
"away,down the hall,,e",
557 {
"away,down the hall,Quarterly financial meeting,e",
560 "Quarterly financial meeting",
564 {
"away,,Quarterly financial meeting,e",
567 "Quarterly financial meeting",
575 info->name =
"parse_valid_presence_data";
576 info->category =
"/funcs/func_presence/";
577 info->summary =
"PRESENCESTATE parsing test";
579 "Ensure that parsing function accepts proper values, and gives proper outputs";
587 char *parse_string =
ast_strdup(tests[i].parse_string);
593 if (parse_result == -1) {
598 if (tests[i].outputs.value !=
state ||
599 strcmp(tests[i].outputs.subtype, subtype) ||
600 strcmp(tests[i].outputs.message,
message) ||
601 strcmp(tests[i].outputs.options,
options)) {
633 info->name =
"parse_invalid_presence_data";
634 info->category =
"/funcs/func_presence/";
635 info->summary =
"PRESENCESTATE parsing test";
637 "Ensure that parsing function rejects improper values";
651 if (parse_result == 0) {
663#define PRES_STATE "away"
664#define PRES_SUBTYPE "down the hall"
665#define PRES_MESSAGE "Quarterly financial meeting"
673static struct test_cb_data *test_cb_data_alloc(
void)
675 struct test_cb_data *cb_data =
ast_calloc(1,
sizeof(*cb_data));
689static void test_cb_data_destroy(
struct test_cb_data *cb_data)
698 struct test_cb_data *cb_data = userdata;
703 ao2_ref(cb_data->presence_state, +1);
710 char *out_state,
size_t out_state_size,
711 char *out_subtype,
size_t out_subtype_size,
712 char *out_message,
size_t out_message_size)
714 RAII_VAR(
struct test_cb_data *, cb_data, test_cb_data_alloc(), test_cb_data_destroy);
723 snprintf(pres,
sizeof(pres),
"%s,%s,%s",
state, subtype,
message);
728 if (
presence_write(
NULL,
"PRESENCESTATE",
"CustomPresence:TestPresenceStateChange", pres)) {
736 ast_copy_string(out_subtype, cb_data->presence_state->subtype, out_subtype_size);
737 ast_copy_string(out_message, cb_data->presence_state->message, out_message_size);
740 ast_db_del(
"CustomPresence",
"TestPresenceStateChange");
748 char out_subtype[32];
749 char out_message[32];
753 info->name =
"test_presence_state_change";
754 info->category =
"/funcs/func_presence/";
755 info->summary =
"presence state change subscription";
757 "Ensure that presence state changes are communicated to subscribers";
763 if (presence_change_common(
test, PRES_STATE, PRES_SUBTYPE, PRES_MESSAGE,
NULL,
764 out_state,
sizeof(out_state),
765 out_subtype,
sizeof(out_subtype),
770 if (strcmp(out_state, PRES_STATE) ||
771 strcmp(out_subtype, PRES_SUBTYPE) ||
772 strcmp(out_message, PRES_MESSAGE)) {
774 PRES_STATE, out_state,
775 PRES_SUBTYPE, out_subtype,
776 PRES_MESSAGE, out_message);
786 char out_subtype[32];
787 char out_message[32];
788 char encoded_subtype[64];
789 char encoded_message[64];
793 info->name =
"test_presence_state_base64_encode";
794 info->category =
"/funcs/func_presence/";
795 info->summary =
"presence state base64 encoding";
797 "Ensure that base64-encoded presence state is stored base64-encoded but\n"
798 "is presented to consumers decoded.";
804 ast_base64encode(encoded_subtype, (
unsigned char *) PRES_SUBTYPE, strlen(PRES_SUBTYPE),
sizeof(encoded_subtype) - 1);
805 ast_base64encode(encoded_message, (
unsigned char *) PRES_MESSAGE, strlen(PRES_MESSAGE),
sizeof(encoded_message) - 1);
807 if (presence_change_common(
test, PRES_STATE, encoded_subtype, encoded_message,
"e",
808 out_state,
sizeof(out_state),
809 out_subtype,
sizeof(out_subtype),
814 if (strcmp(out_state, PRES_STATE) ||
815 strcmp(out_subtype, PRES_SUBTYPE) ||
816 strcmp(out_message, PRES_MESSAGE)) {
818 PRES_STATE, out_state,
819 PRES_SUBTYPE, out_subtype,
820 PRES_MESSAGE, out_message);
853 for (; db_entry; db_entry = db_entry->
next) {
854 const char *dev_name = strrchr(db_entry->
key,
'/') + 1;
857 char *subtype =
NULL;
858 if (dev_name <= (
const char *) 1) {
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
static struct prometheus_metrics_provider provider
General Asterisk PBX channel definitions.
Standard Command Line Interface.
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static int presence_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static char * handle_cli_presencestate_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_presencestate_change(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static enum ast_presence_state custom_presence_callback(const char *data, char **subtype, char **message)
static struct ast_cli_entry cli_funcpresencestate[]
static const char astdb_family[]
static int load_module(void)
static int unload_module(void)
static struct ast_custom_function presence_function
static int presence_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
static int parse_data(char *data, enum ast_presence_state *state, char **subtype, char **message, char **options)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
A set of macros to manage forward-linked lists.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_DEVSTATE_PROVIDER
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
Core PBX routines and definitions.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Presence state management.
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.
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 * ast_presence_state_topic_all(void)
Get presence state topic.
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.
@ AST_PRESENCE_UNAVAILABLE
int ast_presence_state_prov_del(const char *label)
Remove presence state provider.
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.
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
struct stasis_forward * sub
int ast_sem_init(struct ast_sem *sem, int pshared, unsigned int value)
Initialize a semaphore.
int ast_sem_destroy(struct ast_sem *sem)
Destroy a semaphore.
int ast_sem_wait(struct ast_sem *sem)
Decrements the semaphore.
int ast_sem_post(struct ast_sem *sem)
Increments the semaphore, unblocking a waiter if necessary.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
#define stasis_subscribe(topic, callback, data)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Main Channel structure associated with a channel.
descriptor for a cli entry.
int args
This gets set in ast_cli_register()
Data structure associated with a custom dialplan function.
struct ast_db_entry * next
Stasis message payload representing a presence state update.
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define AST_TEST_DEFINE(hdr)
static void test_sub(struct ast_event *event)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.