func_presencestate.c File Reference

Custom presence provider. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/presencestate.h"
#include "asterisk/cli.h"
#include "asterisk/astdb.h"
#include "asterisk/app.h"

Include dependency graph for func_presencestate.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static enum ast_presence_state custom_presence_callback (const char *data, char **subtype, char **message)
static char * handle_cli_presencestate_change (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_presencestate_list (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int load_module (void)
static int parse_data (char *data, enum ast_presence_state *state, char **subtype, char **message, char **options)
static int presence_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int presence_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Gets or sets a presence state in the dialplan" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
static struct ast_module_infoast_module_info = &__mod_info
static const char astdb_family [] = "CustomPresence"
static struct ast_cli_entry cli_funcpresencestate []
static struct ast_custom_function presence_function


Detailed Description

Custom presence provider.

Definition in file func_presencestate.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 884 of file func_presencestate.c.

static void __unreg_module ( void   )  [static]

Definition at line 884 of file func_presencestate.c.

static enum ast_presence_state custom_presence_callback ( const char *  data,
char **  subtype,
char **  message 
) [static]

Definition at line 250 of file func_presencestate.c.

References ast_base64decode(), ast_db_get(), AST_PRESENCE_INVALID, ast_strdup, ast_strlen_zero, buf, NULL, parse_data(), and tmp().

Referenced by load_module().

00251 {
00252    char buf[1301] = "";
00253    enum ast_presence_state state;
00254    char *_options;
00255    char *_message;
00256    char *_subtype;
00257 
00258    ast_db_get(astdb_family, data, buf, sizeof(buf));
00259 
00260    if (parse_data(buf, &state, &_subtype, &_message, &_options)) {
00261       return AST_PRESENCE_INVALID;
00262    }
00263 
00264    if ((strchr(_options, 'e'))) {
00265       char tmp[1301];
00266 
00267       if (ast_strlen_zero(_subtype)) {
00268          *subtype = NULL;
00269       } else {
00270          memset(tmp, 0, sizeof(tmp));
00271          ast_base64decode((unsigned char *) tmp, _subtype, sizeof(tmp) - 1);
00272          *subtype = ast_strdup(tmp);
00273       }
00274 
00275       if (ast_strlen_zero(_message)) {
00276          *message = NULL;
00277       } else {
00278          memset(tmp, 0, sizeof(tmp));
00279          ast_base64decode((unsigned char *) tmp, _message, sizeof(tmp) - 1);
00280          *message = ast_strdup(tmp);
00281       }
00282    } else {
00283       *subtype = ast_strlen_zero(_subtype) ? NULL : ast_strdup(_subtype);
00284       *message = ast_strlen_zero(_message) ? NULL : ast_strdup(_message);
00285    }
00286    return state;
00287 }

static char* handle_cli_presencestate_change ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 366 of file func_presencestate.c.

References ast_cli_args::argc, ast_cli_entry::args, args, ast_cli_args::argv, ast_cli(), ast_cli_complete(), ast_db_put(), AST_PRESENCE_NOT_SET, ast_presence_state_changed_literal(), ast_strdupa, ast_strlen_zero, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cmds, ast_cli_entry::command, ast_cli_args::fd, len(), ast_cli_args::n, NULL, parse_data(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

00367 {
00368     size_t len;
00369    const char *dev, *state, *full_dev;
00370    enum ast_presence_state state_val;
00371    char *message;
00372    char *subtype;
00373    char *options;
00374    char *args;
00375 
00376    switch (cmd) {
00377    case CLI_INIT:
00378       e->command = "presencestate change";
00379       e->usage =
00380          "Usage: presencestate change <entity> <state>[,<subtype>[,message[,options]]]\n"
00381          "       Change a custom presence to a new state.\n"
00382          "       The possible values for the state are:\n"
00383          "NOT_SET | UNAVAILABLE | AVAILABLE | AWAY | XA | CHAT | DND\n"
00384          "Optionally, a custom subtype and message may be provided, along with any options\n"
00385          "accepted by func_presencestate. If the subtype or message provided contain spaces,\n"
00386          "be sure to enclose the data in quotation marks (\"\")\n"
00387          "\n"
00388          "Examples:\n"
00389          "       presencestate change CustomPresence:mystate1 AWAY\n"
00390          "       presencestate change CustomPresence:mystate1 AVAILABLE\n"
00391          "       presencestate change CustomPresence:mystate1 \"Away,upstairs,eating lunch\"\n"
00392          "       \n";
00393       return NULL;
00394    case CLI_GENERATE:
00395    {
00396       static const char * const cmds[] = { "NOT_SET", "UNAVAILABLE", "AVAILABLE", "AWAY",
00397                        "XA", "CHAT", "DND", NULL };
00398 
00399       if (a->pos == e->args + 1) {
00400          return ast_cli_complete(a->word, cmds, a->n);
00401       }
00402 
00403       return NULL;
00404    }
00405    }
00406 
00407    if (a->argc != e->args + 2) {
00408       return CLI_SHOWUSAGE;
00409    }
00410 
00411    len = strlen("CustomPresence:");
00412    full_dev = dev = a->argv[e->args];
00413    state = a->argv[e->args + 1];
00414 
00415    if (strncasecmp(dev, "CustomPresence:", len)) {
00416       ast_cli(a->fd, "The presencestate command can only be used to set 'CustomPresence:' presence state!\n");
00417       return CLI_FAILURE;
00418    }
00419 
00420    dev += len;
00421    if (ast_strlen_zero(dev)) {
00422       return CLI_SHOWUSAGE;
00423    }
00424 
00425    args = ast_strdupa(state);
00426    if (parse_data(args, &state_val, &subtype, &message, &options)) {
00427       return CLI_SHOWUSAGE;
00428    }
00429 
00430    if (state_val == AST_PRESENCE_NOT_SET) {
00431       return CLI_SHOWUSAGE;
00432    }
00433 
00434    ast_cli(a->fd, "Changing %s to %s\n", dev, args);
00435 
00436    ast_db_put(astdb_family, dev, state);
00437 
00438    ast_presence_state_changed_literal(state_val, subtype, message, full_dev);
00439 
00440    return CLI_SUCCESS;
00441 }

static char* handle_cli_presencestate_list ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 295 of file func_presencestate.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CLI_YESNO, ast_copy_string(), ast_db_freetree(), ast_db_gettree(), ast_log, ast_presence_state2str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_db_entry::data, ast_cli_args::fd, ast_db_entry::key, LOG_WARNING, ast_db_entry::next, NULL, parse_data(), and ast_cli_entry::usage.

00296 {
00297    struct ast_db_entry *db_entry, *db_tree;
00298 
00299    switch (cmd) {
00300    case CLI_INIT:
00301       e->command = "presencestate list";
00302       e->usage =
00303          "Usage: presencestate list\n"
00304          "       List all custom presence states that have been set by using\n"
00305          "       the PRESENCE_STATE dialplan function.\n";
00306       return NULL;
00307    case CLI_GENERATE:
00308       return NULL;
00309    }
00310 
00311    if (a->argc != e->args) {
00312       return CLI_SHOWUSAGE;
00313    }
00314 
00315    ast_cli(a->fd, "\n"
00316            "---------------------------------------------------------------------\n"
00317            "--- Custom Presence States ------------------------------------------\n"
00318            "---------------------------------------------------------------------\n"
00319            "---\n");
00320 
00321    db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
00322    if (!db_entry) {
00323       ast_cli(a->fd, "No custom presence states defined\n");
00324       return CLI_SUCCESS;
00325    }
00326    for (; db_entry; db_entry = db_entry->next) {
00327       const char *object_name = strrchr(db_entry->key, '/') + 1;
00328       char state_info[1301];
00329       enum ast_presence_state state;
00330       char *subtype;
00331       char *message;
00332       char *options;
00333 
00334       ast_copy_string(state_info, db_entry->data, sizeof(state_info));
00335       if (parse_data(state_info, &state, &subtype, &message, &options)) {
00336          ast_log(LOG_WARNING, "Invalid CustomPresence entry %s encountered\n", db_entry->data);
00337          continue;
00338       }
00339 
00340       if (object_name <= (const char *) 1) {
00341          continue;
00342       }
00343       ast_cli(a->fd, "--- Name: 'CustomPresence:%s'\n"
00344                    "    --- State: '%s'\n"
00345                   "    --- Subtype: '%s'\n"
00346                   "    --- Message: '%s'\n"
00347                   "    --- Base64 Encoded: '%s'\n"
00348                      "---\n",
00349                   object_name,
00350                   ast_presence_state2str(state),
00351                   subtype,
00352                   message,
00353                   AST_CLI_YESNO(strchr(options, 'e')));
00354    }
00355    ast_db_freetree(db_tree);
00356    db_tree = NULL;
00357 
00358    ast_cli(a->fd,
00359            "---------------------------------------------------------------------\n"
00360            "---------------------------------------------------------------------\n"
00361            "\n");
00362 
00363    return CLI_SUCCESS;
00364 }

static int load_module ( void   )  [static]

Definition at line 842 of file func_presencestate.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_db_freetree(), ast_db_gettree(), ast_free, ast_presence_state_changed(), ast_presence_state_prov_add(), AST_TEST_REGISTER, custom_presence_callback(), ast_db_entry::key, ast_db_entry::next, and NULL.

00843 {
00844    int res = 0;
00845    struct ast_db_entry *db_entry, *db_tree;
00846 
00847    /* Populate the presence state cache on the system with all of the currently
00848     * known custom presence states. */
00849    db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
00850    for (; db_entry; db_entry = db_entry->next) {
00851       const char *dev_name = strrchr(db_entry->key, '/') + 1;
00852       enum ast_presence_state state;
00853       char *message;
00854       char *subtype;
00855       if (dev_name <= (const char *) 1) {
00856          continue;
00857       }
00858       state = custom_presence_callback(dev_name, &subtype, &message);
00859       ast_presence_state_changed(state, subtype, message, "CustomPresence:%s", dev_name);
00860       ast_free(subtype);
00861       ast_free(message);
00862    }
00863    ast_db_freetree(db_tree);
00864    db_tree = NULL;
00865 
00866    res |= ast_custom_function_register(&presence_function);
00867    res |= ast_presence_state_prov_add("CustomPresence", custom_presence_callback);
00868    res |= ast_cli_register_multiple(cli_funcpresencestate, ARRAY_LEN(cli_funcpresencestate));
00869 #ifdef TEST_FRAMEWORK
00870    AST_TEST_REGISTER(test_valid_parse_data);
00871    AST_TEST_REGISTER(test_invalid_parse_data);
00872    AST_TEST_REGISTER(test_presence_state_change);
00873    AST_TEST_REGISTER(test_presence_state_base64_encode);
00874 #endif
00875 
00876    return res;
00877 }

static int parse_data ( char *  data,
enum ast_presence_state state,
char **  subtype,
char **  message,
char **  options 
) [static]

Definition at line 164 of file func_presencestate.c.

References ast_log, AST_PRESENCE_INVALID, ast_presence_state_val(), ast_strlen_zero, LOG_NOTICE, LOG_WARNING, and strsep().

Referenced by custom_presence_callback(), handle_cli_presencestate_change(), handle_cli_presencestate_list(), and presence_write().

00165 {
00166    char *state_str;
00167 
00168    /* data syntax is state,subtype,message,options */
00169    *subtype = "";
00170    *message = "";
00171    *options = "";
00172 
00173    state_str = strsep(&data, ",");
00174    if (ast_strlen_zero(state_str)) {
00175       return -1; /* state is required */
00176    }
00177 
00178    *state = ast_presence_state_val(state_str);
00179 
00180    /* not a valid state */
00181    if (*state == AST_PRESENCE_INVALID) {
00182       ast_log(LOG_WARNING, "Unknown presence state value %s\n", state_str);
00183       return -1;
00184    }
00185 
00186    if (!(*subtype = strsep(&data,","))) {
00187       *subtype = "";
00188       return 0;
00189    }
00190 
00191    if (!(*message = strsep(&data, ","))) {
00192       *message = "";
00193       return 0;
00194    }
00195 
00196    if (!(*options = strsep(&data, ","))) {
00197       *options = "";
00198       return 0;
00199    }
00200 
00201    if (!ast_strlen_zero(*options) && !(strchr(*options, 'e'))) {
00202       ast_log(LOG_NOTICE, "Invalid options  '%s'\n", *options);
00203       return -1;
00204    }
00205 
00206    return 0;
00207 }

static int presence_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 104 of file func_presencestate.c.

References args, AST_APP_ARG, ast_base64encode(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_free, ast_log, AST_PRESENCE_INVALID, ast_presence_state2str(), ast_presence_state_nocache(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, LOG_WARNING, NULL, and parse().

00105 {
00106    int state;
00107    char *message = NULL;
00108    char *subtype = NULL;
00109    char *parse;
00110    int base64encode = 0;
00111    AST_DECLARE_APP_ARGS(args,
00112       AST_APP_ARG(provider);
00113       AST_APP_ARG(field);
00114       AST_APP_ARG(options);
00115    );
00116 
00117    if (ast_strlen_zero(data)) {
00118       ast_log(LOG_WARNING, "PRESENCE_STATE reading requires an argument \n");
00119       return -1;
00120    }
00121 
00122    parse = ast_strdupa(data);
00123 
00124    AST_STANDARD_APP_ARGS(args, parse);
00125 
00126    if (ast_strlen_zero(args.provider) || ast_strlen_zero(args.field)) {
00127       ast_log(LOG_WARNING, "PRESENCE_STATE reading requires both presence provider and presence field arguments. \n");
00128       return -1;
00129    }
00130 
00131    state = ast_presence_state_nocache(args.provider, &subtype, &message);
00132    if (state == AST_PRESENCE_INVALID) {
00133       ast_log(LOG_WARNING, "PRESENCE_STATE unknown \n");
00134       return -1;
00135    }
00136 
00137    if (!(ast_strlen_zero(args.options)) && (strchr(args.options, 'e'))) {
00138       base64encode = 1;
00139    }
00140 
00141    if (!ast_strlen_zero(subtype) && !strcasecmp(args.field, "subtype")) {
00142       if (base64encode) {
00143          ast_base64encode(buf, (unsigned char *) subtype, strlen(subtype), len);
00144       } else {
00145          ast_copy_string(buf, subtype, len);
00146       }
00147    } else if (!ast_strlen_zero(message) && !strcasecmp(args.field, "message")) {
00148       if (base64encode) {
00149          ast_base64encode(buf, (unsigned char *) message, strlen(message), len);
00150       } else {
00151          ast_copy_string(buf, message, len);
00152       }
00153 
00154    } else if (!strcasecmp(args.field, "value")) {
00155       ast_copy_string(buf, ast_presence_state2str(state), len);
00156    }
00157 
00158    ast_free(message);
00159    ast_free(subtype);
00160 
00161    return 0;
00162 }

static int presence_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

Definition at line 209 of file func_presencestate.c.

References args, ast_base64decode(), ast_db_put(), ast_log, ast_presence_state_changed_literal(), ast_strdupa, ast_strlen_zero, len(), LOG_WARNING, parse_data(), and tmp().

00210 {
00211    size_t len = strlen("CustomPresence:");
00212    char *tmp = data;
00213    char *args = ast_strdupa(value);
00214    enum ast_presence_state state;
00215    char *options, *message, *subtype;
00216 
00217    if (strncasecmp(data, "CustomPresence:", len)) {
00218       ast_log(LOG_WARNING, "The PRESENCE_STATE function can only set CustomPresence: presence providers.\n");
00219       return -1;
00220    }
00221    data += len;
00222    if (ast_strlen_zero(data)) {
00223       ast_log(LOG_WARNING, "PRESENCE_STATE function called with no custom device name!\n");
00224       return -1;
00225    }
00226 
00227    if (parse_data(args, &state, &subtype, &message, &options)) {
00228       ast_log(LOG_WARNING, "Invalid arguments to PRESENCE_STATE\n");
00229       return -1;
00230    }
00231 
00232    ast_db_put(astdb_family, data, value);
00233 
00234    if (strchr(options, 'e')) {
00235       /* Let's decode the values before sending them to stasis, yes? */
00236       char decoded_subtype[256] = { 0, };
00237       char decoded_message[256] = { 0, };
00238 
00239       ast_base64decode((unsigned char *) decoded_subtype, subtype, sizeof(decoded_subtype) -1);
00240       ast_base64decode((unsigned char *) decoded_message, message, sizeof(decoded_message) -1);
00241 
00242       ast_presence_state_changed_literal(state, decoded_subtype, decoded_message, tmp);
00243    } else {
00244       ast_presence_state_changed_literal(state, subtype, message, tmp);
00245    }
00246 
00247    return 0;
00248 }

static int unload_module ( void   )  [static]

Definition at line 826 of file func_presencestate.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_presence_state_prov_del(), and AST_TEST_UNREGISTER.

00827 {
00828    int res = 0;
00829 
00830    res |= ast_custom_function_unregister(&presence_function);
00831    res |= ast_presence_state_prov_del("CustomPresence");
00832    res |= ast_cli_unregister_multiple(cli_funcpresencestate, ARRAY_LEN(cli_funcpresencestate));
00833 #ifdef TEST_FRAMEWORK
00834    AST_TEST_UNREGISTER(test_valid_parse_data);
00835    AST_TEST_UNREGISTER(test_invalid_parse_data);
00836    AST_TEST_UNREGISTER(test_presence_state_change);
00837    AST_TEST_UNREGISTER(test_presence_state_base64_encode);
00838 #endif
00839    return res;
00840 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Gets or sets a presence state in the dialplan" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static]

Definition at line 884 of file func_presencestate.c.

Definition at line 884 of file func_presencestate.c.

const char astdb_family[] = "CustomPresence" [static]

Definition at line 102 of file func_presencestate.c.

Initial value:

 {
   AST_CLI_DEFINE(handle_cli_presencestate_list, "List currently know custom presence states"),
   AST_CLI_DEFINE(handle_cli_presencestate_change, "Change a custom presence state"),
}

Definition at line 443 of file func_presencestate.c.

Initial value:

 {
   .name = "PRESENCE_STATE",
   .read = presence_read,
   .write = presence_write,
}

Definition at line 289 of file func_presencestate.c.


Generated on Thu Apr 16 06:31:23 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6