From: Mark Michelson Date: Wed, 4 Apr 2012 19:28:20 +0000 (+0000) Subject: Add Digium phone changes for the funcs directory. X-Git-Tag: 10.4.0-digiumphones-rc1~3^2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94a6534af5a0182b7767e32ef388584ba6de6a53;p=thirdparty%2Fasterisk.git Add Digium phone changes for the funcs directory. git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@361207 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c index 4488577c6f..94dd5083bc 100644 --- a/funcs/func_frame_trace.c +++ b/funcs/func_frame_trace.c @@ -321,6 +321,9 @@ static void print_frame(struct ast_frame *frame) case AST_CONTROL_END_OF_Q: ast_verbose("SubClass: END_OF_Q\n"); break; + case AST_CONTROL_CUSTOM: + ast_verbose("Subclass: Custom"); + break; case AST_CONTROL_UPDATE_RTP_PEER: ast_verbose("SubClass: UPDATE_RTP_PEER\n"); break; diff --git a/funcs/func_presencestate.c b/funcs/func_presencestate.c new file mode 100644 index 0000000000..a8c2b3b88b --- /dev/null +++ b/funcs/func_presencestate.c @@ -0,0 +1,294 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2011-2012, Digium, Inc. + * + * David Vossel + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Custom presence provider + * \ingroup functions + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#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" + +/*** DOCUMENTATION + + + Get or Set a presence state. + + + + The provider of the presence, such as CustomPresence + + + Which field of the presence state information is wanted. + + + + + + + + + + + + + + The PRESENCE_STATE function can be used to retrieve the presence from any + presence provider. For example: + NoOp(SIP/mypeer has presence ${PRESENCE_STATE(SIP/mypeer,value)}) + NoOp(Conference number 1234 has presence message ${PRESENCE_STATE(MeetMe:1234,message)}) + The PRESENCE_STATE function can also be used to set custom presence state from + the dialplan. The CustomPresence: prefix must be used. For example: + Set(PRESENCE_STATE(CustomPresence:lamp1)=away,temporary,Out to lunch) + Set(PRESENCE_STATE(CustomPresence:lamp2)=dnd,,Trying to get work done) + You can subscribe to the status of a custom presence state using a hint in + the dialplan: + exten => 1234,hint,CustomPresence:lamp1 + The possible values for both uses of this function are: + not_set | unavailable | available | away | xa | chat | dnd + + + ***/ + + +static const char astdb_family[] = "CustomPresence"; + +static int presence_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + int state; + char *message = NULL; + char *subtype = NULL; + char *parse; + int base64encode = 0; + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(provider); + AST_APP_ARG(field); + AST_APP_ARG(options); + ); + + if (ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "PRESENCE_STATE reading requires an argument \n"); + return -1; + } + + parse = ast_strdupa(data); + + AST_STANDARD_APP_ARGS(args, parse); + + if (ast_strlen_zero(args.provider) || ast_strlen_zero(args.field)) { + ast_log(LOG_WARNING, "PRESENCE_STATE reading requires both presence provider and presence field arguments. \n"); + return -1; + } + + state = ast_presence_state(args.provider, &subtype, &message); + if (state < 0) { + ast_log(LOG_WARNING, "PRESENCE_STATE unknown \n"); + return -1; + } + + if (!(ast_strlen_zero(args.options)) && (strchr(args.options, 'e'))) { + base64encode = 1; + } + + if (!ast_strlen_zero(subtype) && !strcasecmp(args.field, "subtype")) { + if (base64encode) { + ast_base64encode(buf, (unsigned char *) subtype, strlen(subtype), len); + } else { + ast_copy_string(buf, subtype, len); + } + } else if (!ast_strlen_zero(message) && !strcasecmp(args.field, "message")) { + if (base64encode) { + ast_base64encode(buf, (unsigned char *) message, strlen(message), len); + } else { + ast_copy_string(buf, message, len); + } + + } else if (!strcasecmp(args.field, "value")) { + ast_copy_string(buf, ast_presence_state2str(state), len); + } + + ast_free(message); + ast_free(subtype); + + return 0; +} + +static int parse_data(char *data, int *state, char **subtype, char **message, char **options) +{ + char *state_str; + + /* data syntax is state,subtype,message,options */ + *subtype = ""; + *message = ""; + *options = ""; + + state_str = strsep(&data, ","); + if (ast_strlen_zero(state_str)) { + return -1; /* state is required */ + } + + *state = ast_presence_state_val(state_str); + + /* not a valid state */ + if (*state < 0) { + ast_log(LOG_WARNING, "Unknown presence state value %s\n", state_str); + return -1; + } + + if (!(*subtype = strsep(&data,","))) { + *subtype = ""; + return 0; + } + + if (!(*message = strsep(&data, ","))) { + *message = ""; + return 0; + } + + if (!(*options = strsep(&data, ","))) { + *options = ""; + return 0; + } + + if (!ast_strlen_zero(*options) && !(strchr(*options, 'e'))) { + ast_log(LOG_NOTICE, "Invalid options '%s'\n", *options); + return -1; + } + + return 0; +} + +static int presence_write(struct ast_channel *chan, const char *cmd, char *data, const char *value) +{ + size_t len = strlen("CustomPresence:"); + char *tmp = data; + char *args = ast_strdupa(value); + int state; + char *options, *message, *subtype; + + if (strncasecmp(data, "CustomPresence:", len)) { + ast_log(LOG_WARNING, "The PRESENCE_STATE function can only set CustomPresence: presence providers.\n"); + return -1; + } + data += len; + if (ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "PRESENCE_STATE function called with no custom device name!\n"); + return -1; + } + + if (parse_data(args, &state, &subtype, &message, &options)) { + ast_log(LOG_WARNING, "Invalid arguments to PRESENCE_STATE\n"); + return -1; + } + + ast_db_put(astdb_family, data, value); + + ast_presence_state_changed(tmp); + + return 0; +} + +static enum ast_presence_state custom_presence_callback(const char *data, char **subtype, char **message) +{ + char buf[1301] = ""; + int state; + char *_options; + char *_message; + char *_subtype; + + ast_db_get(astdb_family, data, buf, sizeof(buf)); + + if (parse_data(buf, &state, &_subtype, &_message, &_options)) { + return -1; + } + + if ((strchr(_options, 'e'))) { + char tmp[1301]; + if (ast_strlen_zero(_subtype)) { + *subtype = NULL; + } else { + memset(tmp, 0, sizeof(tmp)); + ast_base64decode((unsigned char *) tmp, _subtype, sizeof(tmp) - 1); + *subtype = ast_strdup(tmp); + } + + if (ast_strlen_zero(_message)) { + *message = NULL; + } else { + memset(tmp, 0, sizeof(tmp)); + ast_base64decode((unsigned char *) tmp, _message, sizeof(tmp) - 1); + *message = ast_strdup(tmp); + } + } else { + *subtype = ast_strlen_zero(_subtype) ? NULL : ast_strdup(_subtype); + *message = ast_strlen_zero(_message) ? NULL : ast_strdup(_message); + } + return state; +} + +static struct ast_custom_function presence_function = { + .name = "PRESENCE_STATE", + .read = presence_read, + .write = presence_write, +}; + +static int unload_module(void) +{ + int res = 0; + + res |= ast_custom_function_unregister(&presence_function); + res |= ast_presence_state_prov_del("CustomPresence"); + return res; +} + +static int load_module(void) +{ + int res = 0; + + res |= ast_custom_function_register(&presence_function); + res |= ast_presence_state_prov_add("CustomPresence", custom_presence_callback); + + return res; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Gets or sets a presence state in the dialplan", + .load = load_module, + .unload = unload_module, + .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, +); +