Phone provisioning application for the asterisk internal http server. More...
#include "asterisk.h"#include <sys/ioctl.h>#include <sys/socket.h>#include <net/if.h>#include "asterisk/channel.h"#include "asterisk/file.h"#include "asterisk/paths.h"#include "asterisk/pbx.h"#include "asterisk/cli.h"#include "asterisk/module.h"#include "asterisk/http.h"#include "asterisk/utils.h"#include "asterisk/app.h"#include "asterisk/strings.h"#include "asterisk/stringfields.h"#include "asterisk/options.h"#include "asterisk/config.h"#include "asterisk/acl.h"#include "asterisk/astobj2.h"#include "asterisk/ast_version.h"
Go to the source code of this file.
Data Structures | |
| struct | extension |
| struct | http_route |
| structure to hold http routes (valid URIs, and the files they link to) More... | |
| struct | phone_profile |
| structure to hold phone profiles read from phoneprov.conf More... | |
| struct | phoneprov_file |
| structure to hold file data More... | |
| struct | pp_variable_lookup |
| Lookup table to translate between users.conf property names and variables for use in phoneprov templates. More... | |
| struct | user |
| structure to hold users read from users.conf More... | |
Defines | |
| #define | FORMAT "%-40.40s %-30.30s\n" |
| #define | MAX_PROFILE_BUCKETS 17 |
| #define | MAX_ROUTE_BUCKETS 563 |
| #define | MAX_USER_BUCKETS 563 |
| #define | VAR_BUF_SIZE 4096 |
Enumerations | |
| enum | pp_variables { PP_MACADDRESS, PP_USERNAME, PP_FULLNAME, PP_SECRET, PP_LABEL, PP_CALLERID, PP_TIMEZONE, PP_LINENUMBER, PP_LINEKEYS, PP_VAR_LIST_LENGTH } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | add_user_extension (struct user *user, struct extension *exten) |
| Add an extension to a user ordered by index/linenumber. | |
| static struct extension * | build_extension (struct ast_config *cfg, const char *name) |
| static void | build_profile (const char *name, struct ast_variable *v) |
| Build a phone profile and add it to the list of phone profiles. | |
| static void | build_route (struct phoneprov_file *pp_file, struct user *user, char *uri) |
| Build a route structure and add it to the list of available http routes. | |
| static struct user * | build_user (const char *mac, struct phone_profile *profile) |
| Build and return a user structure based on gathered config data. | |
| static int | build_user_routes (struct user *user) |
| Add an http route for dynamic files attached to the profile of the user. | |
| static struct extension * | delete_extension (struct extension *exten) |
| static void | delete_file (struct phoneprov_file *file) |
| static void | delete_profiles (void) |
| Delete all phone profiles, freeing their memory. | |
| static void | delete_routes (void) |
| Delete all http routes, freeing their memory. | |
| static void | delete_users (void) |
| Delete all users. | |
| static struct phone_profile * | find_profile (const char *name) |
| Return a phone profile looked up by name. | |
| static struct user * | find_user (const char *macaddress) |
| Return a user looked up by name. | |
| static char * | handle_show_routes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command to list static and dynamic routes. | |
| static int | load_file (const char *filename, char **ret) |
| Read a TEXT file into a string and return the length. | |
| static int | load_module (void) |
| static int | lookup_iface (const char *iface, struct in_addr *address) |
| static int | phoneprov_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers) |
| Callback that is executed everytime an http request is received by this module. | |
| static int | pp_each_extension_helper (struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **bufstr, int len) |
| A dialplan function that can be used to output a template for each extension attached to a user. | |
| static int | pp_each_extension_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static int | pp_each_extension_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len) |
| static int | pp_each_user_helper (struct ast_channel *chan, char *data, char *buf, struct ast_str **bufstr, int len) |
| A dialplan function that can be used to print a string for each phoneprov user. | |
| static int | pp_each_user_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| static int | pp_each_user_read2 (struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len) |
| static int | profile_cmp_fn (void *obj, void *arg, int flags) |
| static void | profile_destructor (void *obj) |
| static int | profile_hash_fn (const void *obj, const int flags) |
| static int | reload (void) |
| static void | route_destructor (void *obj) |
| static int | routes_cmp_fn (void *obj, void *arg, int flags) |
| static int | routes_hash_fn (const void *obj, const int flags) |
| static int | set_config (void) |
| static void | set_timezone_variables (struct varshead *headp, const char *zone) |
| Set all timezone-related variables based on a zone (i.e. America/New_York) | |
| static int | unload_module (void) |
| static struct phone_profile * | unref_profile (struct phone_profile *prof) |
| static struct http_route * | unref_route (struct http_route *route) |
| static struct user * | unref_user (struct user *user) |
| static void | user_destructor (void *obj) |
| Free all memory associated with a user. | |
| static int | users_cmp_fn (void *obj, void *arg, int flags) |
| static int | users_hash_fn (const void *obj, const int flags) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "HTTP Phone Provisioning" , .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, .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct in_addr | __ourip = { .s_addr = 0x00000000, } |
| for use in lookup_iface | |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static char | global_default_profile [80] = "" |
| static char | global_server [80] = "" |
| static char | global_serverport [6] = "" |
| static struct varshead | global_variables |
| List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH. | |
| static ast_mutex_t | globals_lock |
| static struct ao2_container * | http_routes |
| static struct ast_http_uri | phoneprovuri |
| static struct ast_cli_entry | pp_cli [] |
| static struct ast_custom_function | pp_each_extension_function |
| static struct ast_custom_function | pp_each_user_function |
| static struct pp_variable_lookup | pp_variable_list [] |
| static struct ao2_container * | profiles |
| static struct ao2_container * | users |
Phone provisioning application for the asterisk internal http server.
Definition in file res_phoneprov.c.
| #define FORMAT "%-40.40s %-30.30s\n" |
| #define MAX_PROFILE_BUCKETS 17 |
Definition at line 65 of file res_phoneprov.c.
Referenced by load_module().
| #define MAX_ROUTE_BUCKETS 563 |
Definition at line 66 of file res_phoneprov.c.
Referenced by load_module().
| #define MAX_USER_BUCKETS 563 |
Definition at line 67 of file res_phoneprov.c.
Referenced by load_module().
| #define VAR_BUF_SIZE 4096 |
Definition at line 70 of file res_phoneprov.c.
| enum pp_variables |
| PP_MACADDRESS | |
| PP_USERNAME | |
| PP_FULLNAME | |
| PP_SECRET | |
| PP_LABEL | |
| PP_CALLERID | |
| PP_TIMEZONE | |
| PP_LINENUMBER | |
| PP_LINEKEYS | |
| PP_VAR_LIST_LENGTH |
Definition at line 108 of file res_phoneprov.c.
{
PP_MACADDRESS,
PP_USERNAME,
PP_FULLNAME,
PP_SECRET,
PP_LABEL,
PP_CALLERID,
PP_TIMEZONE,
PP_LINENUMBER,
PP_LINEKEYS,
PP_VAR_LIST_LENGTH, /* This entry must always be the last in the list */
};
| static void __reg_module | ( | void | ) | [static] |
Definition at line 1344 of file res_phoneprov.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1344 of file res_phoneprov.c.
Add an extension to a user ordered by index/linenumber.
Definition at line 843 of file res_phoneprov.c.
References ast_free, AST_LIST_EMPTY, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_NEXT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), ast_var_assign(), ast_var_t::entries, user::extensions, phone_profile::headp, extension::headp, extension::index, LOG_WARNING, user::macaddress, ast_var_t::name, user::profile, str, ast_var_t::value, and var.
Referenced by set_config().
{
struct ast_var_t *var;
struct ast_str *str = ast_str_create(16);
if (!str) {
return -1;
}
/* Append profile variables here, and substitute variables on profile
* setvars, so that we can use user specific variables in them */
AST_LIST_TRAVERSE(user->profile->headp, var, entries) {
struct ast_var_t *var2;
ast_str_substitute_variables_varshead(&str, 0, exten->headp, var->value);
if ((var2 = ast_var_assign(var->name, ast_str_buffer(str)))) {
AST_LIST_INSERT_TAIL(exten->headp, var2, entries);
}
}
ast_free(str);
if (AST_LIST_EMPTY(&user->extensions)) {
AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
} else {
struct extension *exten_iter;
AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) {
if (exten->index < exten_iter->index) {
AST_LIST_INSERT_BEFORE_CURRENT(exten, entry);
} else if (exten->index == exten_iter->index) {
ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
return -1;
} else if (!AST_LIST_NEXT(exten_iter, entry)) {
AST_LIST_INSERT_TAIL(&user->extensions, exten, entry);
}
}
AST_LIST_TRAVERSE_SAFE_END;
}
return 0;
}
| static struct extension* build_extension | ( | struct ast_config * | cfg, |
| const char * | name | ||
| ) | [static, read] |
Definition at line 698 of file res_phoneprov.c.
References ast_calloc, ast_calloc_with_stringfields, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_set, ast_strlen_zero(), ast_var_assign(), ast_variable_retrieve(), ast_var_t::entries, exten, extension::headp, extension::index, extension::name, PP_LINEKEYS, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.
Referenced by set_config().
{
struct extension *exten;
struct ast_var_t *var;
const char *tmp;
int i;
if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
return NULL;
}
ast_string_field_set(exten, name, name);
if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) {
ast_free(exten);
exten = NULL;
return NULL;
}
for (i = 0; i < PP_VAR_LIST_LENGTH; i++) {
tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var);
/* If we didn't get a USERNAME variable, set it to the user->name */
if (i == PP_USERNAME && !tmp) {
if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) {
AST_LIST_INSERT_TAIL(exten->headp, var, entries);
}
continue;
} else if (i == PP_TIMEZONE) {
/* perfectly ok if tmp is NULL, will set variables based on server's time zone */
set_timezone_variables(exten->headp, tmp);
} else if (i == PP_LINENUMBER) {
if (!tmp) {
tmp = "1";
}
exten->index = atoi(tmp);
} else if (i == PP_LINEKEYS) {
if (!tmp) {
tmp = "1";
}
}
if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) {
AST_LIST_INSERT_TAIL(exten->headp, var, entries);
}
}
if (!ast_strlen_zero(global_server)) {
if ((var = ast_var_assign("SERVER", global_server)))
AST_LIST_INSERT_TAIL(exten->headp, var, entries);
}
if (!ast_strlen_zero(global_serverport)) {
if ((var = ast_var_assign("SERVER_PORT", global_serverport)))
AST_LIST_INSERT_TAIL(exten->headp, var, entries);
}
return exten;
}
| static void build_profile | ( | const char * | name, |
| struct ast_variable * | v | ||
| ) | [static] |
Build a phone profile and add it to the list of phone profiles.
| name | the name of the profile |
| v | ast_variable from parsing phoneprov.conf |
Definition at line 576 of file res_phoneprov.c.
References ao2_alloc, ao2_link, args, AST_APP_ARG, ast_calloc, ast_calloc_with_stringfields, AST_DECLARE_APP_ARGS, ast_http_ftype2mtype(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strip(), ast_strlen_zero(), ast_var_assign(), build_route(), phone_profile::default_mime_type, phone_profile::dynamic_files, ast_var_t::entries, phoneprov_file::format, global_variables, phone_profile::headp, phoneprov_file::mime_type, ast_var_t::name, ast_variable::name, ast_variable::next, profile_destructor(), S_OR, phone_profile::static_files, phone_profile::staticdir, unref_profile(), ast_var_t::value, ast_variable::value, and var.
Referenced by set_config().
{
struct phone_profile *profile;
struct ast_var_t *var;
if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) {
return;
}
if (ast_string_field_init(profile, 32)) {
profile = unref_profile(profile);
return;
}
if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) {
profile = unref_profile(profile);
return;
}
AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files);
AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files);
ast_string_field_set(profile, name, name);
for (; v; v = v->next) {
if (!strcasecmp(v->name, "mime_type")) {
ast_string_field_set(profile, default_mime_type, v->value);
} else if (!strcasecmp(v->name, "setvar")) {
struct ast_var_t *variable;
char *value_copy = ast_strdupa(v->value);
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(varname);
AST_APP_ARG(varval);
);
AST_NONSTANDARD_APP_ARGS(args, value_copy, '=');
do {
if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
break;
args.varname = ast_strip(args.varname);
args.varval = ast_strip(args.varval);
if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
break;
if ((variable = ast_var_assign(args.varname, args.varval)))
AST_LIST_INSERT_TAIL(profile->headp, variable, entries);
} while (0);
} else if (!strcasecmp(v->name, "staticdir")) {
ast_string_field_set(profile, staticdir, v->value);
} else {
struct phoneprov_file *pp_file;
char *file_extension;
char *value_copy = ast_strdupa(v->value);
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
AST_APP_ARG(mimetype);
);
if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) {
profile = unref_profile(profile);
return;
}
if ((file_extension = strrchr(pp_file->format, '.')))
file_extension++;
AST_STANDARD_APP_ARGS(args, value_copy);
/* Mime type order of preference
* 1) Specific mime-type defined for file in profile
* 2) Mime determined by extension
* 3) Default mime type specified in profile
* 4) text/plain
*/
ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
(S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
if (!strcasecmp(v->name, "static_file")) {
ast_string_field_set(pp_file, format, args.filename);
ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename);
AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry);
/* Add a route for the static files, as their filenames won't change per-user */
build_route(pp_file, NULL, NULL);
} else {
ast_string_field_set(pp_file, format, v->name);
ast_string_field_set(pp_file, template, args.filename);
AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry);
}
}
}
/* Append the global variables to the variables list for this profile.
* This is for convenience later, when we need to provide a single
* variable list for use in substitution. */
ast_mutex_lock(&globals_lock);
AST_LIST_TRAVERSE(&global_variables, var, entries) {
struct ast_var_t *new_var;
if ((new_var = ast_var_assign(var->name, var->value))) {
AST_LIST_INSERT_TAIL(profile->headp, new_var, entries);
}
}
ast_mutex_unlock(&globals_lock);
ao2_link(profiles, profile);
profile = unref_profile(profile);
}
| static void build_route | ( | struct phoneprov_file * | pp_file, |
| struct user * | user, | ||
| char * | uri | ||
| ) | [static] |
Build a route structure and add it to the list of available http routes.
| pp_file | File to link to the route |
| user | User to link to the route (NULL means static route) |
| uri | URI of the route |
Definition at line 549 of file res_phoneprov.c.
References ao2_alloc, ao2_link, ast_log(), ast_string_field_init, ast_string_field_set, http_route::file, phoneprov_file::format, LOG_ERROR, route_destructor(), S_OR, unref_route(), user, and http_route::user.
Referenced by build_profile(), and build_user_routes().
{
struct http_route *route;
if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
return;
}
if (ast_string_field_init(route, 32)) {
ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
route = unref_route(route);
return;
}
ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
route->user = user;
route->file = pp_file;
ao2_link(http_routes, route);
route = unref_route(route);
}
| static struct user* build_user | ( | const char * | mac, |
| struct phone_profile * | profile | ||
| ) | [static, read] |
Build and return a user structure based on gathered config data.
Definition at line 821 of file res_phoneprov.c.
References ao2_alloc, ast_string_field_init, ast_string_field_set, user::macaddress, user::profile, unref_profile(), unref_user(), user, and user_destructor().
Referenced by set_config().
{
struct user *user;
if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
profile = unref_profile(profile);
return NULL;
}
if (ast_string_field_init(user, 32)) {
profile = unref_profile(profile);
user = unref_user(user);
return NULL;
}
ast_string_field_set(user, macaddress, mac);
user->profile = profile; /* already ref counted by find_profile */
return user;
}
| static int build_user_routes | ( | struct user * | user | ) | [static] |
Add an http route for dynamic files attached to the profile of the user.
Definition at line 887 of file res_phoneprov.c.
References ast_free, AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), build_route(), phone_profile::dynamic_files, user::extensions, phoneprov_file::format, user::profile, and str.
Referenced by set_config().
{
struct phoneprov_file *pp_file;
struct ast_str *str;
if (!(str = ast_str_create(16))) {
return -1;
}
AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
ast_str_substitute_variables_varshead(&str, 0, AST_LIST_FIRST(&user->extensions)->headp, pp_file->format);
build_route(pp_file, user, ast_str_buffer(str));
}
ast_free(str);
return 0;
}
Definition at line 684 of file res_phoneprov.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), ast_var_t::entries, extension::headp, and var.
Referenced by set_config(), and user_destructor().
{
struct ast_var_t *var;
while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) {
ast_var_delete(var);
}
ast_free(exten->headp);
ast_string_field_free_memory(exten);
ast_free(exten);
return NULL;
}
| static void delete_file | ( | struct phoneprov_file * | file | ) | [static] |
Definition at line 263 of file res_phoneprov.c.
References ast_string_field_free_memory, and free.
Referenced by profile_destructor().
{
ast_string_field_free_memory(file);
free(file);
}
| static void delete_profiles | ( | void | ) | [static] |
Delete all phone profiles, freeing their memory.
Definition at line 1068 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_profile().
Referenced by reload(), and unload_module().
{
struct ao2_iterator i;
struct phone_profile *profile;
i = ao2_iterator_init(profiles, 0);
while ((profile = ao2_iterator_next(&i))) {
ao2_unlink(profiles, profile);
profile = unref_profile(profile);
}
ao2_iterator_destroy(&i);
}
| static void delete_routes | ( | void | ) | [static] |
Delete all http routes, freeing their memory.
Definition at line 1054 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, and unref_route().
Referenced by reload(), and unload_module().
{
struct ao2_iterator i;
struct http_route *route;
i = ao2_iterator_init(http_routes, 0);
while ((route = ao2_iterator_next(&i))) {
ao2_unlink(http_routes, route);
route = unref_route(route);
}
ao2_iterator_destroy(&i);
}
| static void delete_users | ( | void | ) | [static] |
Delete all users.
Definition at line 807 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, unref_user(), and user.
Referenced by reload(), and unload_module().
{
struct ao2_iterator i;
struct user *user;
i = ao2_iterator_init(users, 0);
while ((user = ao2_iterator_next(&i))) {
ao2_unlink(users, user);
user = unref_user(user);
}
ao2_iterator_destroy(&i);
}
| static struct phone_profile* find_profile | ( | const char * | name | ) | [static, read] |
Return a phone profile looked up by name.
Definition at line 240 of file res_phoneprov.c.
References ao2_find, name, phone_profile::name, and OBJ_POINTER.
Referenced by set_config().
{
struct phone_profile tmp = {
.name = name,
};
return ao2_find(profiles, &tmp, OBJ_POINTER);
}
| static struct user* find_user | ( | const char * | macaddress | ) | [static, read] |
Return a user looked up by name.
Definition at line 766 of file res_phoneprov.c.
References ao2_find, user::macaddress, and OBJ_POINTER.
Referenced by pp_each_extension_helper(), and set_config().
{
struct user tmp = {
.macaddress = macaddress,
};
return ao2_find(users, &tmp, OBJ_POINTER);
}
| static char* handle_show_routes | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
CLI command to list static and dynamic routes.
Definition at line 1217 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, http_route::file, FORMAT, phoneprov_file::template, unref_route(), http_route::uri, ast_cli_entry::usage, and http_route::user.
{
#define FORMAT "%-40.40s %-30.30s\n"
struct ao2_iterator i;
struct http_route *route;
switch(cmd) {
case CLI_INIT:
e->command = "phoneprov show routes";
e->usage =
"Usage: phoneprov show routes\n"
" Lists all registered phoneprov http routes.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
/* This currently iterates over routes twice, but it is the only place I've needed
* to really separate static an dynamic routes, so I've just left it this way. */
ast_cli(a->fd, "Static routes\n\n");
ast_cli(a->fd, FORMAT, "Relative URI", "Physical location");
i = ao2_iterator_init(http_routes, 0);
while ((route = ao2_iterator_next(&i))) {
if (!route->user)
ast_cli(a->fd, FORMAT, route->uri, route->file->template);
route = unref_route(route);
}
ao2_iterator_destroy(&i);
ast_cli(a->fd, "\nDynamic routes\n\n");
ast_cli(a->fd, FORMAT, "Relative URI", "Template");
i = ao2_iterator_init(http_routes, 0);
while ((route = ao2_iterator_next(&i))) {
if (route->user)
ast_cli(a->fd, FORMAT, route->uri, route->file->template);
route = unref_route(route);
}
ao2_iterator_destroy(&i);
return CLI_SUCCESS;
}
| static int load_file | ( | const char * | filename, |
| char ** | ret | ||
| ) | [static] |
Read a TEXT file into a string and return the length.
Definition at line 317 of file res_phoneprov.c.
References ast_malloc, f, free, and len().
Referenced by phoneprov_callback(), and pp_each_extension_helper().
{
int len = 0;
FILE *f;
if (!(f = fopen(filename, "r"))) {
*ret = NULL;
return -1;
}
fseek(f, 0, SEEK_END);
len = ftell(f);
fseek(f, 0, SEEK_SET);
if (!(*ret = ast_malloc(len + 1)))
return -2;
if (len != fread(*ret, sizeof(char), len, f)) {
free(*ret);
*ret = NULL;
return -3;
}
fclose(f);
(*ret)[len] = '\0';
return len;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 1273 of file res_phoneprov.c.
References ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_http_uri_link(), AST_LIST_HEAD_INIT_NOLOCK, ast_mutex_init, global_variables, MAX_PROFILE_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, profile_cmp_fn(), profile_hash_fn(), routes_cmp_fn(), routes_hash_fn(), set_config(), users_cmp_fn(), and users_hash_fn().
{
profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, profile_hash_fn, profile_cmp_fn);
http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, routes_hash_fn, routes_cmp_fn);
users = ao2_container_alloc(MAX_USER_BUCKETS, users_hash_fn, users_cmp_fn);
AST_LIST_HEAD_INIT_NOLOCK(&global_variables);
ast_mutex_init(&globals_lock);
ast_custom_function_register(&pp_each_user_function);
ast_custom_function_register(&pp_each_extension_function);
ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli));
set_config();
ast_http_uri_link(&phoneprovuri);
return 0;
}
| static int lookup_iface | ( | const char * | iface, |
| struct in_addr * | address | ||
| ) | [static] |
Definition at line 202 of file res_phoneprov.c.
References ast_copy_string(), ast_log(), errno, LOG_ERROR, and LOG_WARNING.
Referenced by set_config().
{
int mysock, res = 0;
struct ifreq ifr;
struct sockaddr_in *sin;
memset(&ifr, 0, sizeof(ifr));
ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (mysock < 0) {
ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno));
return -1;
}
res = ioctl(mysock, SIOCGIFADDR, &ifr);
close(mysock);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
memcpy(address, &__ourip, sizeof(__ourip));
return -1;
} else {
sin = (struct sockaddr_in *)&ifr.ifr_addr;
memcpy(address, &sin->sin_addr, sizeof(*address));
return 0;
}
}
| static int phoneprov_callback | ( | struct ast_tcptls_session_instance * | ser, |
| const struct ast_http_uri * | urih, | ||
| const char * | uri, | ||
| enum ast_http_method | method, | ||
| struct ast_variable * | get_vars, | ||
| struct ast_variable * | headers | ||
| ) | [static] |
Callback that is executed everytime an http request is received by this module.
Definition at line 407 of file res_phoneprov.c.
References ao2_find, ast_config_AST_DATA_DIR, ast_free, ast_http_error(), AST_HTTP_GET, AST_HTTP_HEAD, ast_http_send(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_substitute_variables_varshead(), ast_strlen_zero(), ast_var_assign(), user::extensions, ast_tcptls_session_instance::fd, http_route::file, extension::headp, len(), load_file(), LOG_ERROR, LOG_WARNING, phoneprov_file::mime_type, name, OBJ_POINTER, phoneprov_file::template, unref_route(), http_route::uri, http_route::user, and var.
{
struct http_route *route;
struct http_route search_route = {
.uri = uri,
};
struct ast_str *result;
char path[PATH_MAX];
char *file = NULL;
int len;
int fd;
struct ast_str *http_header;
if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
return -1;
}
if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) {
goto out404;
}
snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
if (!route->user) { /* Static file */
fd = open(path, O_RDONLY);
if (fd < 0) {
goto out500;
}
len = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if (len < 0) {
ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
close(fd);
goto out500;
}
http_header = ast_str_create(80);
ast_str_set(&http_header, 0, "Content-type: %s\r\n",
route->file->mime_type);
ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
close(fd);
route = unref_route(route);
return 0;
} else { /* Dynamic file */
struct ast_str *tmp;
len = load_file(path, &file);
if (len < 0) {
ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
if (file) {
ast_free(file);
}
goto out500;
}
if (!file) {
goto out500;
}
if (!(tmp = ast_str_create(len))) {
if (file) {
ast_free(file);
}
goto out500;
}
/* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
* the IP address we are listening on that the phone contacted for this config file */
if (ast_strlen_zero(global_server)) {
union {
struct sockaddr sa;
struct sockaddr_in sa_in;
} name;
socklen_t namelen = sizeof(name.sa);
int res;
if ((res = getsockname(ser->fd, &name.sa, &namelen))) {
ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
} else {
struct ast_var_t *var;
struct extension *exten_iter;
if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) {
AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries);
}
}
}
}
ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file);
if (file) {
ast_free(file);
}
http_header = ast_str_create(80);
ast_str_set(&http_header, 0, "Content-type: %s\r\n",
route->file->mime_type);
if (!(result = ast_str_create(512))) {
ast_log(LOG_ERROR, "Could not create result string!\n");
if (tmp) {
ast_free(tmp);
}
ast_free(http_header);
goto out500;
}
ast_str_append(&result, 0, "%s", ast_str_buffer(tmp));
ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
if (tmp) {
ast_free(tmp);
}
route = unref_route(route);
return 0;
}
out404:
ast_http_error(ser, 404, "Not Found", "Nothing to see here. Move along.");
return -1;
out500:
route = unref_route(route);
ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
return -1;
}
| static int pp_each_extension_helper | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| char * | buf, | ||
| struct ast_str ** | bufstr, | ||
| int | len | ||
| ) | [static] |
A dialplan function that can be used to output a template for each extension attached to a user.
Definition at line 1139 of file res_phoneprov.c.
References args, AST_APP_ARG, ast_build_string(), ast_config_AST_DATA_DIR, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_TRAVERSE, ast_log(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), ast_strlen_zero(), exten, user::extensions, find_user(), extension::headp, len(), load_file(), LOG_WARNING, str, unref_user(), and user.
Referenced by pp_each_extension_read(), and pp_each_extension_read2().
{
struct user *user;
struct extension *exten;
char path[PATH_MAX];
char *file;
int filelen;
struct ast_str *str;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(mac);
AST_APP_ARG(template);
);
AST_STANDARD_APP_ARGS(args, data);
if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n");
return 0;
}
if (!(user = find_user(args.mac))) {
ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
return 0;
}
snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
filelen = load_file(path, &file);
if (filelen < 0) {
ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
if (file) {
ast_free(file);
}
return 0;
}
if (!file) {
return 0;
}
if (!(str = ast_str_create(filelen))) {
return 0;
}
AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
ast_str_substitute_variables_varshead(&str, 0, exten->headp, file);
if (buf) {
size_t slen = len;
ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
} else {
ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
}
}
ast_free(file);
ast_free(str);
user = unref_user(user);
return 0;
}
| static int pp_each_extension_read | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| char * | buf, | ||
| size_t | len | ||
| ) | [static] |
Definition at line 1200 of file res_phoneprov.c.
References pp_each_extension_helper().
{
return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
}
| static int pp_each_extension_read2 | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| struct ast_str ** | buf, | ||
| ssize_t | len | ||
| ) | [static] |
Definition at line 1205 of file res_phoneprov.c.
References pp_each_extension_helper().
{
return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
}
| static int pp_each_user_helper | ( | struct ast_channel * | chan, |
| char * | data, | ||
| char * | buf, | ||
| struct ast_str ** | bufstr, | ||
| int | len | ||
| ) | [static] |
A dialplan function that can be used to print a string for each phoneprov user.
Definition at line 1082 of file res_phoneprov.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, args, AST_APP_ARG, ast_build_string(), AST_DECLARE_APP_ARGS, ast_free, AST_LIST_FIRST, AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables_varshead(), ast_strlen_zero(), user::extensions, len(), user::macaddress, str, unref_user(), and user.
Referenced by pp_each_user_read(), and pp_each_user_read2().
{
char *tmp;
struct ao2_iterator i;
struct user *user;
struct ast_str *str;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(string);
AST_APP_ARG(exclude_mac);
);
AST_STANDARD_APP_ARGS(args, data);
if (!(str = ast_str_create(16))) {
return -1;
}
/* Fix data by turning %{ into ${ */
while ((tmp = strstr(args.string, "%{")))
*tmp = '$';
i = ao2_iterator_init(users, 0);
while ((user = ao2_iterator_next(&i))) {
if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
continue;
}
ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string);
if (buf) {
size_t slen = len;
ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
} else {
ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
}
user = unref_user(user);
}
ao2_iterator_destroy(&i);
ast_free(str);
return 0;
}
| static int pp_each_user_read | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| char * | buf, | ||
| size_t | len | ||
| ) | [static] |
Definition at line 1122 of file res_phoneprov.c.
References pp_each_user_helper().
{
return pp_each_user_helper(chan, data, buf, NULL, len);
}
| static int pp_each_user_read2 | ( | struct ast_channel * | chan, |
| const char * | cmd, | ||
| char * | data, | ||
| struct ast_str ** | buf, | ||
| ssize_t | len | ||
| ) | [static] |
Definition at line 1127 of file res_phoneprov.c.
References pp_each_user_helper().
{
return pp_each_user_helper(chan, data, NULL, buf, len);
}
| static int profile_cmp_fn | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 256 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and phone_profile::name.
Referenced by load_module().
{
const struct phone_profile *profile1 = obj, *profile2 = arg;
return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH | CMP_STOP : 0;
}
| static void profile_destructor | ( | void * | obj | ) | [static] |
Definition at line 269 of file res_phoneprov.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), delete_file(), phone_profile::dynamic_files, ast_var_t::entries, phone_profile::headp, phone_profile::static_files, and var.
Referenced by build_profile().
{
struct phone_profile *profile = obj;
struct phoneprov_file *file;
struct ast_var_t *var;
while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry)))
delete_file(file);
while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry)))
delete_file(file);
while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries)))
ast_var_delete(var);
ast_free(profile->headp);
ast_string_field_free_memory(profile);
}
| static int profile_hash_fn | ( | const void * | obj, |
| const int | flags | ||
| ) | [static] |
Definition at line 249 of file res_phoneprov.c.
References ast_str_case_hash(), and phone_profile::name.
Referenced by load_module().
{
const struct phone_profile *profile = obj;
return ast_str_case_hash(profile->name);
}
| static int reload | ( | void | ) | [static] |
Definition at line 1321 of file res_phoneprov.c.
References AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_var_delete(), delete_profiles(), delete_routes(), delete_users(), ast_var_t::entries, global_variables, set_config(), and var.
{
struct ast_var_t *var;
delete_routes();
delete_users();
delete_profiles();
ast_mutex_lock(&globals_lock);
while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) {
ast_var_delete(var);
}
ast_mutex_unlock(&globals_lock);
set_config();
return 0;
}
| static void route_destructor | ( | void * | obj | ) | [static] |
Definition at line 309 of file res_phoneprov.c.
References ast_string_field_free_memory.
Referenced by build_route().
{
struct http_route *route = obj;
ast_string_field_free_memory(route);
}
| static int routes_cmp_fn | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 302 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and http_route::uri.
Referenced by load_module().
{
const struct http_route *route1 = obj, *route2 = arg;
return !strcasecmp(route1->uri, route2->uri) ? CMP_MATCH | CMP_STOP : 0;
}
| static int routes_hash_fn | ( | const void * | obj, |
| const int | flags | ||
| ) | [static] |
Definition at line 295 of file res_phoneprov.c.
References ast_str_case_hash(), and http_route::uri.
Referenced by load_module().
{
const struct http_route *route = obj;
return ast_str_case_hash(route->uri);
}
| static int set_config | ( | void | ) | [static] |
Definition at line 906 of file res_phoneprov.c.
References add_user_extension(), ao2_link, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_inet_ntoa(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_true(), ast_var_assign(), ast_variable_browse(), ast_variable_retrieve(), build_extension(), build_profile(), build_user(), build_user_routes(), CONFIG_STATUS_FILEINVALID, delete_extension(), ast_var_t::entries, exten, find_profile(), find_user(), global_variables, LOG_ERROR, LOG_WARNING, lookup_iface(), user::macaddress, ast_variable::name, extension::name, ast_variable::next, S_OR, unref_user(), user, ast_variable::value, and var.
Referenced by load_module(), and reload().
{
struct ast_config *cfg, *phoneprov_cfg;
char *cat;
struct ast_variable *v;
struct ast_flags config_flags = { 0 };
struct ast_var_t *var;
/* Try to grab the port from sip.conf. If we don't get it here, we'll set it
* to whatever is set in phoneprov.conf or default to 5060 */
if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport));
ast_config_destroy(cfg);
}
if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_WARNING, "Unable to load users.conf\n");
return 0;
}
/* Go ahead and load global variables from users.conf so we can append to profiles */
for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
if (!strcasecmp(v->name, "vmexten")) {
if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) {
ast_mutex_lock(&globals_lock);
AST_LIST_INSERT_TAIL(&global_variables, var, entries);
ast_mutex_unlock(&globals_lock);
}
}
if (!strcasecmp(v->name, "localextenlength")) {
if ((var = ast_var_assign("EXTENSION_LENGTH", v->value)))
ast_mutex_lock(&globals_lock);
AST_LIST_INSERT_TAIL(&global_variables, var, entries);
ast_mutex_unlock(&globals_lock);
}
}
if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags)) || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
ast_config_destroy(cfg);
return -1;
}
cat = NULL;
while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
if (!strcasecmp(cat, "general")) {
for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) {
if (!strcasecmp(v->name, "serveraddr"))
ast_copy_string(global_server, v->value, sizeof(global_server));
else if (!strcasecmp(v->name, "serveriface")) {
struct in_addr addr;
lookup_iface(v->value, &addr);
ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server));
} else if (!strcasecmp(v->name, "serverport"))
ast_copy_string(global_serverport, v->value, sizeof(global_serverport));
else if (!strcasecmp(v->name, "default_profile"))
ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile));
}
} else
build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
}
ast_config_destroy(phoneprov_cfg);
cat = NULL;
while ((cat = ast_category_browse(cfg, cat))) {
const char *tmp, *mac;
struct user *user;
struct phone_profile *profile;
struct extension *exten;
if (!strcasecmp(cat, "general")) {
continue;
}
if (!strcasecmp(cat, "authentication"))
continue;
if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp)))
continue;
if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) {
ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
continue;
}
tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile);
if (ast_strlen_zero(tmp)) {
ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac);
continue;
}
if (!(user = find_user(mac))) {
if (!(profile = find_profile(tmp))) {
ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp);
continue;
}
if (!(user = build_user(mac, profile))) {
ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress);
continue;
}
if (!(exten = build_extension(cfg, cat))) {
ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress);
user = unref_user(user);
continue;
}
if (add_user_extension(user, exten)) {
ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
user = unref_user(user);
exten = delete_extension(exten);
continue;
}
if (build_user_routes(user)) {
ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress);
user = unref_user(user);
continue;
}
ao2_link(users, user);
user = unref_user(user);
} else {
if (!(exten = build_extension(cfg, cat))) {
ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress);
user = unref_user(user);
continue;
}
if (add_user_extension(user, exten)) {
ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
user = unref_user(user);
exten = delete_extension(exten);
continue;
}
user = unref_user(user);
}
}
ast_config_destroy(cfg);
return 0;
}
| static void set_timezone_variables | ( | struct varshead * | headp, |
| const char * | zone | ||
| ) | [static] |
Set all timezone-related variables based on a zone (i.e. America/New_York)
| headp | pointer to list of user variables |
| zone | A time zone. NULL sets variables based on timezone of the machine |
Definition at line 350 of file res_phoneprov.c.
References ast_get_dst_info(), AST_LIST_INSERT_TAIL, ast_localtime(), ast_var_assign(), ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_mon, and var.
Referenced by build_extension().
{
time_t utc_time;
int dstenable;
time_t dststart;
time_t dstend;
struct ast_tm tm_info;
int tzoffset;
char buffer[21];
struct ast_var_t *var;
struct timeval when;
time(&utc_time);
ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone);
snprintf(buffer, sizeof(buffer), "%d", tzoffset);
var = ast_var_assign("TZOFFSET", buffer);
if (var)
AST_LIST_INSERT_TAIL(headp, var, entries);
if (!dstenable)
return;
if ((var = ast_var_assign("DST_ENABLE", "1")))
AST_LIST_INSERT_TAIL(headp, var, entries);
when.tv_sec = dststart;
ast_localtime(&when, &tm_info, zone);
snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1);
if ((var = ast_var_assign("DST_START_MONTH", buffer)))
AST_LIST_INSERT_TAIL(headp, var, entries);
snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
if ((var = ast_var_assign("DST_START_MDAY", buffer)))
AST_LIST_INSERT_TAIL(headp, var, entries);
snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
if ((var = ast_var_assign("DST_START_HOUR", buffer)))
AST_LIST_INSERT_TAIL(headp, var, entries);
when.tv_sec = dstend;
ast_localtime(&when, &tm_info, zone);
snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1);
if ((var = ast_var_assign("DST_END_MONTH", buffer)))
AST_LIST_INSERT_TAIL(headp, var, entries);
snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
if ((var = ast_var_assign("DST_END_MDAY", buffer)))
AST_LIST_INSERT_TAIL(headp, var, entries);
snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
if ((var = ast_var_assign("DST_END_HOUR", buffer)))
AST_LIST_INSERT_TAIL(headp, var, entries);
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 1294 of file res_phoneprov.c.
References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_http_uri_unlink(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_var_delete(), delete_profiles(), delete_routes(), delete_users(), ast_var_t::entries, global_variables, and var.
{
struct ast_var_t *var;
ast_http_uri_unlink(&phoneprovuri);
ast_custom_function_unregister(&pp_each_user_function);
ast_custom_function_unregister(&pp_each_extension_function);
ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli));
delete_routes();
delete_users();
delete_profiles();
ao2_ref(profiles, -1);
ao2_ref(http_routes, -1);
ao2_ref(users, -1);
ast_mutex_lock(&globals_lock);
while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) {
ast_var_delete(var);
}
ast_mutex_unlock(&globals_lock);
ast_mutex_destroy(&globals_lock);
return 0;
}
| static struct phone_profile* unref_profile | ( | struct phone_profile * | prof | ) | [static, read] |
Definition at line 232 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_profile(), build_user(), delete_profiles(), and user_destructor().
{
ao2_ref(prof, -1);
return NULL;
}
| static struct http_route* unref_route | ( | struct http_route * | route | ) | [static, read] |
Definition at line 288 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_route(), delete_routes(), handle_show_routes(), and phoneprov_callback().
{
ao2_ref(route, -1);
return NULL;
}
Definition at line 758 of file res_phoneprov.c.
References ao2_ref.
Referenced by build_user(), delete_users(), pp_each_extension_helper(), pp_each_user_helper(), and set_config().
{
ao2_ref(user, -1);
return NULL;
}
| static void user_destructor | ( | void * | obj | ) | [static] |
Free all memory associated with a user.
Definition at line 790 of file res_phoneprov.c.
References AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), exten, user::extensions, user::profile, and unref_profile().
Referenced by build_user().
{
struct user *user = obj;
struct extension *exten;
while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
exten = delete_extension(exten);
}
if (user->profile) {
user->profile = unref_profile(user->profile);
}
ast_string_field_free_memory(user);
}
| static int users_cmp_fn | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 782 of file res_phoneprov.c.
References CMP_MATCH, CMP_STOP, and user::macaddress.
Referenced by load_module().
{
const struct user *user1 = obj, *user2 = arg;
return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0;
}
| static int users_hash_fn | ( | const void * | obj, |
| const int | flags | ||
| ) | [static] |
Definition at line 775 of file res_phoneprov.c.
References ast_str_case_hash(), and user::macaddress.
Referenced by load_module().
{
const struct user *user = obj;
return ast_str_case_hash(user->macaddress);
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "HTTP Phone Provisioning" , .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, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1344 of file res_phoneprov.c.
struct in_addr __ourip = { .s_addr = 0x00000000, } [static] |
for use in lookup_iface
Definition at line 104 of file res_phoneprov.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1344 of file res_phoneprov.c.
char global_default_profile[80] = "" [static] |
Default profile to use if one isn't specified
Definition at line 195 of file res_phoneprov.c.
char global_server[80] = "" [static] |
Server to substitute into templates
Definition at line 193 of file res_phoneprov.c.
char global_serverport[6] = "" [static] |
Server port to substitute into templates
Definition at line 194 of file res_phoneprov.c.
struct varshead global_variables [static] |
List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.
Definition at line 198 of file res_phoneprov.c.
Referenced by build_profile(), load_module(), reload(), set_config(), and unload_module().
ast_mutex_t globals_lock [static] |
Definition at line 199 of file res_phoneprov.c.
struct ao2_container* http_routes [static] |
Definition at line 190 of file res_phoneprov.c.
struct ast_http_uri phoneprovuri [static] |
Definition at line 1264 of file res_phoneprov.c.
struct ast_cli_entry pp_cli[] [static] |
{
AST_CLI_DEFINE(handle_show_routes, "Show registered phoneprov http routes"),
}
Definition at line 1260 of file res_phoneprov.c.
struct ast_custom_function pp_each_extension_function [static] |
{
.name = "PP_EACH_EXTENSION",
.read = pp_each_extension_read,
.read2 = pp_each_extension_read2,
}
Definition at line 1210 of file res_phoneprov.c.
struct ast_custom_function pp_each_user_function [static] |
{
.name = "PP_EACH_USER",
.read = pp_each_user_read,
.read2 = pp_each_user_read2,
}
Definition at line 1132 of file res_phoneprov.c.
struct pp_variable_lookup pp_variable_list[] [static] |
Referenced by build_extension().
struct ao2_container* profiles [static] |
Definition at line 189 of file res_phoneprov.c.
struct ao2_container* users [static] |
Definition at line 191 of file res_phoneprov.c.