#include "asterisk.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.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 | 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... | |
struct | users |
list of users found in the config file More... | |
Defines | |
#define | FORMAT "%-40.40s %-30.30s\n" |
#define | MAX_PROFILE_BUCKETS 17 |
#define | MAX_ROUTE_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_VAR_LIST_LENGTH } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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 (struct ast_config *cfg, const char *name, 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 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_user (struct user *user) |
Free all memory associated with a user. | |
static void | delete_users (void) |
Destroy entire user list. | |
static struct phone_profile * | find_profile (const char *name) |
Return a phone profile looked up by name. | |
static char * | ftype2mtype (const char *ftype) |
Return mime type based on extension. | |
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 struct ast_str * | phoneprov_callback (struct ast_tcptls_session_instance *ser, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength) |
Callback that is executed everytime an http request is received by this module. | |
static int | pp_each_user_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
A dialplan function that can be used to print a string for each phoneprov user. | |
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) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct in_addr | __ourip = { .s_addr = 0x00000000, } |
for use in lookup_iface | |
static const struct ast_module_info * | ast_module_info = &__mod_info |
char | global_default_profile [80] = "" |
char | global_server [80] = "" |
char | global_serverport [6] = "" |
varshead | global_variables |
List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH. | |
static struct ao2_container * | http_routes |
struct { | |
char * ext | |
char * mtype | |
} | mimetypes [] |
Extensions whose mime types we think we know. | |
static struct ast_http_uri | phoneprovuri |
static struct ast_cli_entry | pp_cli [] |
static struct ast_custom_function | pp_each_user_function |
static struct pp_variable_lookup | pp_variable_list [] |
Lookup table to translate between users.conf property names and variables for use in phoneprov templates. | |
static struct ao2_container * | profiles |
Terry Wilson <twilson@digium.com>
Definition in file res_phoneprov.c.
#define FORMAT "%-40.40s %-30.30s\n" |
#define MAX_PROFILE_BUCKETS 17 |
#define MAX_ROUTE_BUCKETS 563 |
#define VAR_BUF_SIZE 4096 |
Definition at line 63 of file res_phoneprov.c.
enum pp_variables |
PP_MACADDRESS | |
PP_USERNAME | |
PP_FULLNAME | |
PP_SECRET | |
PP_LABEL | |
PP_CALLERID | |
PP_TIMEZONE | |
PP_VAR_LIST_LENGTH |
Definition at line 70 of file res_phoneprov.c.
00070 { 00071 PP_MACADDRESS, 00072 PP_USERNAME, 00073 PP_FULLNAME, 00074 PP_SECRET, 00075 PP_LABEL, 00076 PP_CALLERID, 00077 PP_TIMEZONE, 00078 PP_VAR_LIST_LENGTH, /* This entry must always be the last in the list */ 00079 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 1049 of file res_phoneprov.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1049 of file res_phoneprov.c.
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 490 of file res_phoneprov.c.
References ao2_alloc(), AST_APP_ARG, ast_calloc, AST_DECLARE_APP_ARGS, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strip(), ast_strlen_zero(), ast_var_assign(), ast_var_t::entries, ast_variable::name, ast_variable::next, profile_destructor(), unref_profile(), ast_variable::value, and var.
Referenced by set_config().
00491 { 00492 struct phone_profile *profile; 00493 struct ast_var_t *var; 00494 00495 if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) 00496 return; 00497 00498 if (ast_string_field_init(profile, 32)) { 00499 profile = unref_profile(profile); 00500 return; 00501 } 00502 00503 if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) { 00504 profile = unref_profile(profile); 00505 return; 00506 } 00507 00508 AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files); 00509 AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files); 00510 00511 ast_string_field_set(profile, name, name); 00512 for (; v; v = v->next) { 00513 if (!strcasecmp(v->name, "mime_type")) { 00514 ast_string_field_set(profile, default_mime_type, v->value); 00515 } else if (!strcasecmp(v->name, "setvar")) { 00516 struct ast_var_t *var; 00517 char *value_copy = ast_strdupa(v->value); 00518 00519 AST_DECLARE_APP_ARGS(args, 00520 AST_APP_ARG(varname); 00521 AST_APP_ARG(varval); 00522 ); 00523 00524 AST_NONSTANDARD_APP_ARGS(args, value_copy, '='); 00525 do { 00526 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00527 break; 00528 args.varname = ast_strip(args.varname); 00529 args.varval = ast_strip(args.varval); 00530 if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval)) 00531 break; 00532 if ((var = ast_var_assign(args.varname, args.varval))) 00533 AST_LIST_INSERT_TAIL(profile->headp, var, entries); 00534 } while (0); 00535 } else if (!strcasecmp(v->name, "staticdir")) { 00536 ast_string_field_set(profile, staticdir, v->value); 00537 } else { 00538 struct phoneprov_file *pp_file; 00539 char *file_extension; 00540 char *value_copy = ast_strdupa(v->value); 00541 00542 AST_DECLARE_APP_ARGS(args, 00543 AST_APP_ARG(filename); 00544 AST_APP_ARG(mimetype); 00545 ); 00546 00547 if (!(pp_file = ast_calloc(1, sizeof(*pp_file)))) { 00548 profile = unref_profile(profile); 00549 return; 00550 } 00551 if (ast_string_field_init(pp_file, 32)) { 00552 ast_free(pp_file); 00553 profile = unref_profile(profile); 00554 return; 00555 } 00556 00557 if ((file_extension = strrchr(pp_file->format, '.'))) 00558 file_extension++; 00559 00560 AST_STANDARD_APP_ARGS(args, value_copy); 00561 00562 /* Mime type order of preference 00563 * 1) Specific mime-type defined for file in profile 00564 * 2) Mime determined by extension 00565 * 3) Default mime type specified in profile 00566 * 4) text/plain 00567 */ 00568 ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype, (S_OR(S_OR(ftype2mtype(file_extension), profile->default_mime_type), "text/plain")))); 00569 00570 if (!strcasecmp(v->name, "static_file")) { 00571 ast_string_field_set(pp_file, format, args.filename); 00572 ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename); 00573 AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry); 00574 /* Add a route for the static files, as their filenames won't change per-user */ 00575 build_route(pp_file, NULL, NULL); 00576 } else { 00577 ast_string_field_set(pp_file, format, v->name); 00578 ast_string_field_set(pp_file, template, args.filename); 00579 AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry); 00580 } 00581 } 00582 } 00583 00584 /* Append the global variables to the variables list for this profile. 00585 * This is for convenience later, when we need to provide a single 00586 * variable list for use in substitution. */ 00587 AST_LIST_TRAVERSE(&global_variables, var, entries) { 00588 struct ast_var_t *new_var; 00589 if ((new_var = ast_var_assign(var->name, var->value))) 00590 AST_LIST_INSERT_TAIL(profile->headp, new_var, entries); 00591 } 00592 00593 ao2_link(profiles, profile); 00594 00595 profile = unref_profile(profile); 00596 }
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 464 of file res_phoneprov.c.
References ao2_alloc(), ao2_link(), ast_log(), ast_string_field_init, ast_string_field_set, phoneprov_file::format, http_routes, LOG_ERROR, route_destructor(), S_OR, unref_route(), and user.
00465 { 00466 struct http_route *route; 00467 00468 if (!(route = ao2_alloc(sizeof(*route), route_destructor))) 00469 return; 00470 00471 if (ast_string_field_init(route, 32)) { 00472 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format); 00473 route = unref_route(route); 00474 return; 00475 } 00476 00477 ast_string_field_set(route, uri, S_OR(uri, pp_file->format)); 00478 route->user = user; 00479 route->file = pp_file; 00480 00481 ao2_link(http_routes, route); 00482 00483 route = unref_route(route); 00484 }
static struct user* build_user | ( | struct ast_config * | cfg, | |
const char * | name, | |||
const char * | mac, | |||
struct phone_profile * | profile | |||
) | [static] |
Build and return a user structure based on gathered config data.
Definition at line 684 of file res_phoneprov.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_init, ast_string_field_set, ast_var_assign(), ast_variable_retrieve(), delete_user(), ast_var_t::entries, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), unref_profile(), user, and var.
00685 { 00686 struct user *user; 00687 struct ast_var_t *var; 00688 const char *tmp; 00689 int i; 00690 00691 if (!(user = ast_calloc(1, sizeof(*user)))) { 00692 profile = unref_profile(profile); 00693 return NULL; 00694 } 00695 00696 if (!(user->headp = ast_calloc(1, sizeof(*user->headp)))) { 00697 profile = unref_profile(profile); 00698 ast_free(user); 00699 return NULL; 00700 } 00701 00702 if (ast_string_field_init(user, 32)) { 00703 profile = unref_profile(profile); 00704 delete_user(user); 00705 return NULL; 00706 } 00707 00708 ast_string_field_set(user, name, name); 00709 ast_string_field_set(user, macaddress, mac); 00710 user->profile = profile; /* already ref counted by find_profile */ 00711 00712 for (i = 0; i < PP_VAR_LIST_LENGTH; i++) { 00713 tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var); 00714 00715 /* If we didn't get a USERNAME variable, set it to the user->name */ 00716 if (i == PP_USERNAME && !tmp) { 00717 if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, user->name))) { 00718 AST_LIST_INSERT_TAIL(user->headp, var, entries); 00719 } 00720 continue; 00721 } else if (i == PP_TIMEZONE) { 00722 /* perfectly ok if tmp is NULL, will set variables based on server's time zone */ 00723 set_timezone_variables(user->headp, tmp); 00724 } 00725 00726 if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) 00727 AST_LIST_INSERT_TAIL(user->headp, var, entries); 00728 } 00729 00730 if (!ast_strlen_zero(global_server)) { 00731 if ((var = ast_var_assign("SERVER", global_server))) 00732 AST_LIST_INSERT_TAIL(user->headp, var, entries); 00733 } 00734 00735 if (!ast_strlen_zero(global_serverport)) { 00736 if ((var = ast_var_assign("SERVER_PORT", global_serverport))) 00737 AST_LIST_INSERT_TAIL(user->headp, var, entries); 00738 } 00739 00740 /* Append profile variables here, and substitute variables on profile 00741 * setvars, so that we can use user specific variables in them */ 00742 AST_LIST_TRAVERSE(user->profile->headp, var, entries) { 00743 char expand_buf[VAR_BUF_SIZE] = {0,}; 00744 struct ast_var_t *var2; 00745 00746 pbx_substitute_variables_varshead(user->headp, var->value, expand_buf, sizeof(expand_buf)); 00747 if ((var2 = ast_var_assign(var->name, expand_buf))) 00748 AST_LIST_INSERT_TAIL(user->headp, var2, entries); 00749 } 00750 00751 return user; 00752 }
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 755 of file res_phoneprov.c.
References AST_LIST_TRAVERSE, build_route(), phoneprov_file::entry, phoneprov_file::format, pbx_substitute_variables_varshead(), user, and VAR_BUF_SIZE.
00756 { 00757 struct phoneprov_file *pp_file; 00758 00759 AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) { 00760 char expand_buf[VAR_BUF_SIZE] = { 0, }; 00761 00762 pbx_substitute_variables_varshead(user->headp, pp_file->format, expand_buf, sizeof(expand_buf)); 00763 build_route(pp_file, user, expand_buf); 00764 } 00765 00766 return 0; 00767 }
static void delete_file | ( | struct phoneprov_file * | file | ) | [static] |
Definition at line 242 of file res_phoneprov.c.
References ast_string_field_free_memory, and free.
Referenced by profile_destructor().
00243 { 00244 ast_string_field_free_memory(file); 00245 free(file); 00246 }
static void delete_profiles | ( | void | ) | [static] |
Delete all phone profiles, freeing their memory.
Definition at line 893 of file res_phoneprov.c.
References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), profiles, and unref_profile().
Referenced by reload(), and unload_module().
00894 { 00895 struct ao2_iterator i; 00896 struct phone_profile *profile; 00897 00898 i = ao2_iterator_init(profiles, 0); 00899 while ((profile = ao2_iterator_next(&i))) { 00900 ao2_unlink(profiles, profile); 00901 profile = unref_profile(profile); 00902 } 00903 }
static void delete_routes | ( | void | ) | [static] |
Delete all http routes, freeing their memory.
Definition at line 880 of file res_phoneprov.c.
References ao2_iterator_init(), ao2_iterator_next(), ao2_unlink(), http_routes, and unref_route().
Referenced by reload(), and unload_module().
00881 { 00882 struct ao2_iterator i; 00883 struct http_route *route; 00884 00885 i = ao2_iterator_init(http_routes, 0); 00886 while ((route = ao2_iterator_next(&i))) { 00887 ao2_unlink(http_routes, route); 00888 route = unref_route(route); 00889 } 00890 }
static void delete_user | ( | struct user * | user | ) | [static] |
Free all memory associated with a user.
Definition at line 599 of file res_phoneprov.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), ast_var_t::entries, free, unref_profile(), user, and var.
Referenced by build_user(), and delete_users().
00600 { 00601 struct ast_var_t *var; 00602 00603 while ((var = AST_LIST_REMOVE_HEAD(user->headp, entries))) 00604 ast_var_delete(var); 00605 00606 ast_free(user->headp); 00607 ast_string_field_free_memory(user); 00608 user->profile = unref_profile(user->profile); 00609 free(user); 00610 }
static void delete_users | ( | void | ) | [static] |
Destroy entire user list.
Definition at line 613 of file res_phoneprov.c.
References AST_LIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, delete_user(), phoneprov_file::entry, and user.
00614 { 00615 struct user *user; 00616 00617 AST_RWLIST_WRLOCK(&users); 00618 while ((user = AST_LIST_REMOVE_HEAD(&users, entry))) 00619 delete_user(user); 00620 AST_RWLIST_UNLOCK(&users); 00621 }
static struct phone_profile* find_profile | ( | const char * | name | ) | [static] |
Return a phone profile looked up by name.
Definition at line 219 of file res_phoneprov.c.
References ao2_find(), phone_profile::name, OBJ_POINTER, and profiles.
00220 { 00221 struct phone_profile tmp = { 00222 .name = name, 00223 }; 00224 00225 return ao2_find(profiles, &tmp, OBJ_POINTER); 00226 }
static char* ftype2mtype | ( | const char * | ftype | ) | [static] |
Return mime type based on extension.
Definition at line 165 of file res_phoneprov.c.
References ARRAY_LEN, ast_strlen_zero(), ext, and mimetypes.
00166 { 00167 int x; 00168 00169 if (ast_strlen_zero(ftype)) 00170 return NULL; 00171 00172 for (x = 0;x < ARRAY_LEN(mimetypes);x++) { 00173 if (!strcasecmp(ftype, mimetypes[x].ext)) 00174 return mimetypes[x].mtype; 00175 } 00176 00177 return NULL; 00178 }
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 946 of file res_phoneprov.c.
References 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, http_routes, phoneprov_file::template, unref_route(), http_route::uri, ast_cli_entry::usage, and http_route::user.
00947 { 00948 #define FORMAT "%-40.40s %-30.30s\n" 00949 struct ao2_iterator i; 00950 struct http_route *route; 00951 00952 switch(cmd) { 00953 case CLI_INIT: 00954 e->command = "phoneprov show routes"; 00955 e->usage = 00956 "Usage: phoneprov show routes\n" 00957 " Lists all registered phoneprov http routes.\n"; 00958 return NULL; 00959 case CLI_GENERATE: 00960 return NULL; 00961 } 00962 00963 /* This currently iterates over routes twice, but it is the only place I've needed 00964 * to really separate static an dynamic routes, so I've just left it this way. */ 00965 ast_cli(a->fd, "Static routes\n\n"); 00966 ast_cli(a->fd, FORMAT, "Relative URI", "Physical location"); 00967 i = ao2_iterator_init(http_routes, 0); 00968 while ((route = ao2_iterator_next(&i))) { 00969 if (!route->user) 00970 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 00971 route = unref_route(route); 00972 } 00973 00974 ast_cli(a->fd, "\nDynamic routes\n\n"); 00975 ast_cli(a->fd, FORMAT, "Relative URI", "Template"); 00976 00977 i = ao2_iterator_init(http_routes, 0); 00978 while ((route = ao2_iterator_next(&i))) { 00979 if (route->user) 00980 ast_cli(a->fd, FORMAT, route->uri, route->file->template); 00981 route = unref_route(route); 00982 } 00983 00984 return CLI_SUCCESS; 00985 }
static int load_file | ( | const char * | filename, | |
char ** | ret | |||
) | [static] |
Read a TEXT file into a string and return the length.
Definition at line 296 of file res_phoneprov.c.
References ast_malloc, f, free, and len().
Referenced by phoneprov_callback().
00297 { 00298 int len = 0; 00299 FILE *f; 00300 00301 if (!(f = fopen(filename, "r"))) { 00302 *ret = NULL; 00303 return -1; 00304 } 00305 00306 fseek(f, 0, SEEK_END); 00307 len = ftell(f); 00308 fseek(f, 0, SEEK_SET); 00309 if (!(*ret = ast_malloc(len + 1))) 00310 return -2; 00311 00312 if (len != fread(*ret, sizeof(char), len, f)) { 00313 free(*ret); 00314 *ret = NULL; 00315 return -3; 00316 } 00317 00318 fclose(f); 00319 00320 (*ret)[len] = '\0'; 00321 00322 return len; 00323 }
static int load_module | ( | void | ) | [static] |
Definition at line 998 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, global_variables, http_routes, MAX_PROFILE_BUCKETS, MAX_ROUTE_BUCKETS, phoneprovuri, pp_cli, pp_each_user_function, profile_cmp_fn(), profile_hash_fn(), profiles, routes_cmp_fn(), routes_hash_fn(), and set_config().
00999 { 01000 profiles = ao2_container_alloc(MAX_PROFILE_BUCKETS, profile_hash_fn, profile_cmp_fn); 01001 01002 http_routes = ao2_container_alloc(MAX_ROUTE_BUCKETS, routes_hash_fn, routes_cmp_fn); 01003 01004 AST_LIST_HEAD_INIT_NOLOCK(&global_variables); 01005 01006 ast_custom_function_register(&pp_each_user_function); 01007 ast_cli_register_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01008 01009 set_config(); 01010 ast_http_uri_link(&phoneprovuri); 01011 01012 return 0; 01013 }
static int lookup_iface | ( | const char * | iface, | |
struct in_addr * | address | |||
) | [static] |
Definition at line 181 of file res_phoneprov.c.
References ast_copy_string(), ast_log(), errno, LOG_ERROR, and LOG_WARNING.
Referenced by set_config().
00182 { 00183 int mysock, res = 0; 00184 struct ifreq ifr; 00185 struct sockaddr_in *sin; 00186 00187 memset(&ifr, 0, sizeof(ifr)); 00188 ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 00189 00190 mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 00191 if (mysock < 0) { 00192 ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno)); 00193 return -1; 00194 } 00195 00196 res = ioctl(mysock, SIOCGIFADDR, &ifr); 00197 00198 close(mysock); 00199 00200 if (res < 0) { 00201 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno)); 00202 memcpy(address, &__ourip, sizeof(__ourip)); 00203 return -1; 00204 } else { 00205 sin = (struct sockaddr_in *)&ifr.ifr_addr; 00206 memcpy(address, &sin->sin_addr, sizeof(*address)); 00207 return 0; 00208 } 00209 }
static struct ast_str* phoneprov_callback | ( | struct ast_tcptls_session_instance * | ser, | |
const char * | uri, | |||
struct ast_variable * | vars, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Callback that is executed everytime an http request is received by this module.
Definition at line 326 of file res_phoneprov.c.
References ao2_find(), ast_calloc, ast_config_AST_DATA_DIR, ast_debug, ast_free, ast_get_version(), ast_http_error(), ast_inet_ntoa(), AST_LIST_INSERT_TAIL, ast_localtime(), ast_log(), ast_str_append(), ast_str_create(), ast_strftime(), ast_strlen_zero(), ast_tvnow(), ast_var_assign(), buf, ast_var_t::entries, errno, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, http_route::file, user::headp, http_routes, len(), load_file(), LOG_WARNING, phoneprov_file::mime_type, OBJ_POINTER, pbx_substitute_variables_varshead(), strdup, phoneprov_file::template, unref_route(), http_route::uri, http_route::user, var, and VAR_BUF_SIZE.
00327 { 00328 struct http_route *route; 00329 struct http_route search_route = { 00330 .uri = uri, 00331 }; 00332 struct ast_str *result = ast_str_create(512); 00333 char path[PATH_MAX]; 00334 char *file = NULL; 00335 int len; 00336 int fd; 00337 char buf[256]; 00338 struct timeval tv = ast_tvnow(); 00339 struct ast_tm tm; 00340 00341 if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) 00342 goto out404; 00343 00344 snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template); 00345 00346 if (!route->user) { /* Static file */ 00347 00348 fd = open(path, O_RDONLY); 00349 if (fd < 0) 00350 goto out500; 00351 00352 len = lseek(fd, 0, SEEK_END); 00353 lseek(fd, 0, SEEK_SET); 00354 if (len < 0) { 00355 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00356 close(fd); 00357 goto out500; 00358 } 00359 00360 ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&tv, &tm, "GMT")); 00361 fprintf(ser->f, "HTTP/1.1 200 OK\r\n" 00362 "Server: Asterisk/%s\r\n" 00363 "Date: %s\r\n" 00364 "Connection: close\r\n" 00365 "Cache-Control: no-cache, no-store\r\n" 00366 "Content-Length: %d\r\n" 00367 "Content-Type: %s\r\n\r\n", 00368 ast_get_version(), buf, len, route->file->mime_type); 00369 00370 while ((len = read(fd, buf, sizeof(buf))) > 0) 00371 if (fwrite(buf, 1, len, ser->f) != len) { 00372 if (errno != EPIPE) { 00373 ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno)); 00374 } else { 00375 ast_debug(3, "Requester closed the connection while downloading '%s'\n", path); 00376 } 00377 break; 00378 } 00379 00380 close(fd); 00381 route = unref_route(route); 00382 return NULL; 00383 } else { /* Dynamic file */ 00384 int bufsize; 00385 char *tmp; 00386 00387 len = load_file(path, &file); 00388 if (len < 0) { 00389 ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len); 00390 if (file) 00391 ast_free(file); 00392 goto out500; 00393 } 00394 00395 if (!file) 00396 goto out500; 00397 00398 /* XXX This is a hack -- maybe sum length of all variables in route->user->headp and add that? */ 00399 bufsize = len + VAR_BUF_SIZE; 00400 00401 /* malloc() instead of alloca() here, just in case the file is bigger than 00402 * we have enough stack space for. */ 00403 if (!(tmp = ast_calloc(1, bufsize))) { 00404 if (file) 00405 ast_free(file); 00406 goto out500; 00407 } 00408 00409 /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to 00410 * the IP address we are listening on that the phone contacted for this config file */ 00411 if (ast_strlen_zero(global_server)) { 00412 struct sockaddr name; 00413 socklen_t namelen = sizeof(name); 00414 int res; 00415 00416 if ((res = getsockname(ser->fd, &name, &namelen))) 00417 ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n"); 00418 else { 00419 struct ast_var_t *var; 00420 00421 if ((var = ast_var_assign("SERVER", ast_inet_ntoa(((struct sockaddr_in *)&name)->sin_addr)))) 00422 AST_LIST_INSERT_TAIL(route->user->headp, var, entries); 00423 } 00424 } 00425 00426 pbx_substitute_variables_varshead(route->user->headp, file, tmp, bufsize); 00427 00428 if (file) 00429 ast_free(file); 00430 00431 ast_str_append(&result, 0, 00432 "Content-Type: %s\r\n" 00433 "Content-length: %d\r\n" 00434 "\r\n" 00435 "%s", route->file->mime_type, (int) strlen(tmp), tmp); 00436 00437 if (tmp) 00438 ast_free(tmp); 00439 00440 route = unref_route(route); 00441 00442 return result; 00443 } 00444 00445 out404: 00446 *status = 404; 00447 *title = strdup("Not Found"); 00448 *contentlength = 0; 00449 return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along."); 00450 00451 out500: 00452 route = unref_route(route); 00453 *status = 500; 00454 *title = strdup("Internal Server Error"); 00455 *contentlength = 0; 00456 return ast_http_error(500, "Internal Error", NULL, "An internal error has occured."); 00457 }
static int pp_each_user_exec | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
A dialplan function that can be used to print a string for each phoneprov user.
Definition at line 906 of file res_phoneprov.c.
References AST_APP_ARG, ast_build_string(), AST_DECLARE_APP_ARGS, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_STANDARD_APP_ARGS, ast_strlen_zero(), user::entry, pbx_substitute_variables_varshead(), user, and VAR_BUF_SIZE.
00907 { 00908 char *tmp, expand_buf[VAR_BUF_SIZE] = {0,}; 00909 struct user *user; 00910 AST_DECLARE_APP_ARGS(args, 00911 AST_APP_ARG(string); 00912 AST_APP_ARG(exclude_mac); 00913 ); 00914 AST_STANDARD_APP_ARGS(args, data); 00915 00916 /* Fix data by turning %{ into ${ */ 00917 while ((tmp = strstr(args.string, "%{"))) 00918 *tmp = '$'; 00919 00920 AST_RWLIST_RDLOCK(&users); 00921 AST_RWLIST_TRAVERSE(&users, user, entry) { 00922 if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) 00923 continue; 00924 pbx_substitute_variables_varshead(user->headp, args.string, expand_buf, sizeof(expand_buf)); 00925 ast_build_string(&buf, &len, "%s", expand_buf); 00926 } 00927 AST_RWLIST_UNLOCK(&users); 00928 00929 return 0; 00930 }
static int profile_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 235 of file res_phoneprov.c.
References CMP_MATCH, and phone_profile::name.
Referenced by load_module().
00236 { 00237 const struct phone_profile *profile1 = obj, *profile2 = arg; 00238 00239 return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH : 0; 00240 }
static void profile_destructor | ( | void * | obj | ) | [static] |
Definition at line 248 of file res_phoneprov.c.
References AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), delete_file(), phone_profile::dynamic_files, ast_var_t::entries, phoneprov_file::entry, free, phone_profile::headp, phone_profile::static_files, and var.
Referenced by build_profile().
00249 { 00250 struct phone_profile *profile = obj; 00251 struct phoneprov_file *file; 00252 struct ast_var_t *var; 00253 00254 while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry))) 00255 delete_file(file); 00256 00257 while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry))) 00258 delete_file(file); 00259 00260 while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries))) 00261 ast_var_delete(var); 00262 00263 free(profile->headp); 00264 ast_string_field_free_memory(profile); 00265 }
static int profile_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 228 of file res_phoneprov.c.
References ast_str_hash(), and phone_profile::name.
Referenced by load_module().
00229 { 00230 const struct phone_profile *profile = obj; 00231 00232 return ast_str_hash(profile->name); 00233 }
static int reload | ( | void | ) | [static] |
Definition at line 1035 of file res_phoneprov.c.
References delete_profiles(), delete_routes(), delete_users(), and set_config().
01036 { 01037 delete_routes(); 01038 delete_users(); 01039 delete_profiles(); 01040 set_config(); 01041 01042 return 0; 01043 }
static void route_destructor | ( | void * | obj | ) | [static] |
Definition at line 288 of file res_phoneprov.c.
References ast_string_field_free_memory.
Referenced by build_route().
00289 { 00290 struct http_route *route = obj; 00291 00292 ast_string_field_free_memory(route); 00293 }
static int routes_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 281 of file res_phoneprov.c.
References CMP_MATCH, and http_route::uri.
Referenced by load_module().
00282 { 00283 const struct http_route *route1 = obj, *route2 = arg; 00284 00285 return !strcmp(route1->uri, route2->uri) ? CMP_MATCH : 0; 00286 }
static int routes_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 274 of file res_phoneprov.c.
References ast_str_hash(), and http_route::uri.
Referenced by load_module().
00275 { 00276 const struct http_route *route = obj; 00277 00278 return ast_str_hash(route->uri); 00279 }
static int set_config | ( | void | ) | [static] |
Definition at line 770 of file res_phoneprov.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_variable_browse(), ast_variable_retrieve(), build_profile(), LOG_ERROR, lookup_iface(), ast_variable::name, ast_variable::next, S_OR, and ast_variable::value.
00771 { 00772 struct ast_config *cfg; 00773 char *cat; 00774 struct ast_variable *v; 00775 struct ast_flags config_flags = { 0 }; 00776 00777 /* Try to grab the port from sip.conf. If we don't get it here, we'll set it 00778 * to whatever is set in phoneprov.conf or default to 5060 */ 00779 if ((cfg = ast_config_load("sip.conf", config_flags))) { 00780 ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport)); 00781 ast_config_destroy(cfg); 00782 } 00783 00784 if (!(cfg = ast_config_load("phoneprov.conf", config_flags))) { 00785 ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n"); 00786 ast_config_destroy(cfg); 00787 return -1; 00788 } 00789 00790 cat = NULL; 00791 while ((cat = ast_category_browse(cfg, cat))) { 00792 if (!strcasecmp(cat, "general")) { 00793 for (v = ast_variable_browse(cfg, cat); v; v = v->next) { 00794 if (!strcasecmp(v->name, "serveraddr")) 00795 ast_copy_string(global_server, v->value, sizeof(global_server)); 00796 else if (!strcasecmp(v->name, "serveriface")) { 00797 struct in_addr addr; 00798 lookup_iface(v->value, &addr); 00799 ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server)); 00800 } else if (!strcasecmp(v->name, "serverport")) 00801 ast_copy_string(global_serverport, v->value, sizeof(global_serverport)); 00802 else if (!strcasecmp(v->name, "default_profile")) 00803 ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile)); 00804 } 00805 } else 00806 build_profile(cat, ast_variable_browse(cfg, cat)); 00807 } 00808 00809 ast_config_destroy(cfg); 00810 00811 if (!(cfg = ast_config_load("users.conf", config_flags))) { 00812 ast_log(LOG_WARNING, "Unable to load users.cfg\n"); 00813 return 0; 00814 } 00815 00816 cat = NULL; 00817 while ((cat = ast_category_browse(cfg, cat))) { 00818 const char *tmp, *mac; 00819 struct user *user; 00820 struct phone_profile *profile; 00821 struct ast_var_t *var; 00822 00823 if (!strcasecmp(cat, "general")) { 00824 for (v = ast_variable_browse(cfg, cat); v; v = v->next) { 00825 if (!strcasecmp(v->name, "vmexten")) { 00826 if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) 00827 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00828 } 00829 if (!strcasecmp(v->name, "localextenlength")) { 00830 if ((var = ast_var_assign("EXTENSION_LENGTH", v->value))) 00831 AST_LIST_INSERT_TAIL(&global_variables, var, entries); 00832 } 00833 } 00834 } 00835 00836 if (!strcasecmp(cat, "authentication")) 00837 continue; 00838 00839 if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp))) 00840 continue; 00841 00842 if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) { 00843 ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat); 00844 continue; 00845 } 00846 00847 tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile); 00848 if (ast_strlen_zero(tmp)) { 00849 ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac); 00850 continue; 00851 } 00852 00853 if (!(profile = find_profile(tmp))) { 00854 ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp); 00855 continue; 00856 } 00857 00858 if (!(user = build_user(cfg, cat, mac, profile))) { 00859 ast_log(LOG_WARNING, "Could not create user %s - skipping.\n", cat); 00860 continue; 00861 } 00862 00863 if (build_user_routes(user)) { 00864 ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->name); 00865 delete_user(user); 00866 continue; 00867 } 00868 00869 AST_RWLIST_WRLOCK(&users); 00870 AST_RWLIST_INSERT_TAIL(&users, user, entry); 00871 AST_RWLIST_UNLOCK(&users); 00872 } 00873 00874 ast_config_destroy(cfg); 00875 00876 return 0; 00877 }
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 627 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_user().
00628 { 00629 time_t utc_time; 00630 int dstenable; 00631 time_t dststart; 00632 time_t dstend; 00633 struct ast_tm tm_info; 00634 int tzoffset; 00635 char buffer[21]; 00636 struct ast_var_t *var; 00637 struct timeval tv; 00638 00639 time(&utc_time); 00640 ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone); 00641 snprintf(buffer, sizeof(buffer), "%d", tzoffset); 00642 var = ast_var_assign("TZOFFSET", buffer); 00643 if (var) 00644 AST_LIST_INSERT_TAIL(headp, var, entries); 00645 00646 if (!dstenable) 00647 return; 00648 00649 if ((var = ast_var_assign("DST_ENABLE", "1"))) 00650 AST_LIST_INSERT_TAIL(headp, var, entries); 00651 00652 tv.tv_sec = dststart; 00653 ast_localtime(&tv, &tm_info, zone); 00654 00655 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1); 00656 if ((var = ast_var_assign("DST_START_MONTH", buffer))) 00657 AST_LIST_INSERT_TAIL(headp, var, entries); 00658 00659 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); 00660 if ((var = ast_var_assign("DST_START_MDAY", buffer))) 00661 AST_LIST_INSERT_TAIL(headp, var, entries); 00662 00663 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); 00664 if ((var = ast_var_assign("DST_START_HOUR", buffer))) 00665 AST_LIST_INSERT_TAIL(headp, var, entries); 00666 00667 tv.tv_sec = dstend; 00668 ast_localtime(&tv, &tm_info, zone); 00669 00670 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1); 00671 if ((var = ast_var_assign("DST_END_MONTH", buffer))) 00672 AST_LIST_INSERT_TAIL(headp, var, entries); 00673 00674 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday); 00675 if ((var = ast_var_assign("DST_END_MDAY", buffer))) 00676 AST_LIST_INSERT_TAIL(headp, var, entries); 00677 00678 snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour); 00679 if ((var = ast_var_assign("DST_END_HOUR", buffer))) 00680 AST_LIST_INSERT_TAIL(headp, var, entries); 00681 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1015 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_var_delete(), delete_profiles(), delete_routes(), delete_users(), ast_var_t::entries, global_variables, http_routes, phoneprovuri, pp_cli, pp_each_user_function, profiles, and var.
01016 { 01017 struct ast_var_t *var; 01018 01019 ast_http_uri_unlink(&phoneprovuri); 01020 ast_custom_function_unregister(&pp_each_user_function); 01021 ast_cli_unregister_multiple(pp_cli, ARRAY_LEN(pp_cli)); 01022 01023 delete_routes(); 01024 delete_users(); 01025 delete_profiles(); 01026 ao2_ref(profiles, -1); 01027 ao2_ref(http_routes, -1); 01028 01029 while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) 01030 ast_var_delete(var); 01031 01032 return 0; 01033 }
static struct phone_profile* unref_profile | ( | struct phone_profile * | prof | ) | [static] |
Definition at line 211 of file res_phoneprov.c.
References ao2_ref().
Referenced by build_profile(), build_user(), delete_profiles(), and delete_user().
00212 { 00213 ao2_ref(prof, -1); 00214 00215 return NULL; 00216 }
static struct http_route* unref_route | ( | struct http_route * | route | ) | [static] |
Definition at line 267 of file res_phoneprov.c.
References ao2_ref().
Referenced by build_route(), delete_routes(), handle_show_routes(), and phoneprov_callback().
00268 { 00269 ao2_ref(route, -1); 00270 00271 return NULL; 00272 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1049 of file res_phoneprov.c.
struct in_addr __ourip = { .s_addr = 0x00000000, } [static] |
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1049 of file res_phoneprov.c.
char* ext |
Definition at line 146 of file res_phoneprov.c.
char global_default_profile[80] = "" |
Default profile to use if one isn't specified
Definition at line 159 of file res_phoneprov.c.
char global_server[80] = "" |
Server to substitute into templates
Definition at line 157 of file res_phoneprov.c.
char global_serverport[6] = "" |
Server port to substitute into templates
Definition at line 158 of file res_phoneprov.c.
struct varshead global_variables |
List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.
Definition at line 162 of file res_phoneprov.c.
Referenced by load_module(), and unload_module().
struct ao2_container* http_routes [static] |
Definition at line 141 of file res_phoneprov.c.
Referenced by build_route(), delete_routes(), handle_show_routes(), load_module(), phoneprov_callback(), and unload_module().
struct { ... } mimetypes[] [static] |
Extensions whose mime types we think we know.
char* mtype |
Definition at line 147 of file res_phoneprov.c.
struct ast_http_uri phoneprovuri [static] |
struct ast_cli_entry pp_cli[] [static] |
Initial value:
{ { .handler = handle_show_routes , .summary = "Show registered phoneprov http routes" ,__VA_ARGS__ }, }
Definition at line 987 of file res_phoneprov.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function pp_each_user_function [static] |
struct pp_variable_lookup pp_variable_list[] [static] |
Lookup table to translate between users.conf property names and variables for use in phoneprov templates.
Referenced by build_user().
struct ao2_container* profiles [static] |
Definition at line 140 of file res_phoneprov.c.
Referenced by delete_profiles(), find_profile(), load_module(), and unload_module().