Mon Jun 27 16:51:19 2011

Asterisk developer's documentation


res_phoneprov.c File Reference

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 extensionbuild_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 userbuild_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 extensiondelete_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_profilefind_profile (const char *name)
 Return a phone profile looked up by name.
static struct userfind_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_profileunref_profile (struct phone_profile *prof)
static struct http_routeunref_route (struct http_route *route)
static struct userunref_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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_infoast_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_containerhttp_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 []
 Lookup table to translate between users.conf property names and variables for use in phoneprov templates.
static struct ao2_containerprofiles
static struct ao2_containerusers


Detailed Description

Phone provisioning application for the asterisk internal http server.

Author:
Matthew Brooks <mbrooks@digium.com>

Terry Wilson <twilson@digium.com>

Definition in file res_phoneprov.c.


Define Documentation

#define FORMAT   "%-40.40s %-30.30s\n"

#define MAX_PROFILE_BUCKETS   17

Definition at line 61 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_ROUTE_BUCKETS   563

Definition at line 62 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_USER_BUCKETS   563

Definition at line 63 of file res_phoneprov.c.

#define VAR_BUF_SIZE   4096

Definition at line 66 of file res_phoneprov.c.


Enumeration Type Documentation

enum pp_variables

Enumerator:
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 104 of file res_phoneprov.c.

00104                   {
00105    PP_MACADDRESS,
00106    PP_USERNAME,
00107    PP_FULLNAME,
00108    PP_SECRET,
00109    PP_LABEL,
00110    PP_CALLERID,
00111    PP_TIMEZONE,
00112    PP_LINENUMBER,
00113    PP_LINEKEYS,
00114    PP_VAR_LIST_LENGTH,  /* This entry must always be the last in the list */
00115 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1340 of file res_phoneprov.c.

static void __unreg_module ( void   )  [static]

Definition at line 1340 of file res_phoneprov.c.

static int add_user_extension ( struct user user,
struct extension exten 
) [static]

Add an extension to a user ordered by index/linenumber.

Definition at line 839 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, phoneprov_file::entry, exten, extension::index, LOG_WARNING, str, user, and var.

00840 {
00841    struct ast_var_t *var;
00842    struct ast_str *str = ast_str_create(16);
00843 
00844    if (!str) {
00845       return -1;
00846    }
00847 
00848    /* Append profile variables here, and substitute variables on profile
00849     * setvars, so that we can use user specific variables in them */
00850    AST_LIST_TRAVERSE(user->profile->headp, var, entries) {
00851       struct ast_var_t *var2;
00852 
00853       ast_str_substitute_variables_varshead(&str, 0, exten->headp, var->value);
00854       if ((var2 = ast_var_assign(var->name, ast_str_buffer(str)))) {
00855          AST_LIST_INSERT_TAIL(exten->headp, var2, entries);
00856       }
00857    }
00858 
00859    ast_free(str);
00860 
00861    if (AST_LIST_EMPTY(&user->extensions)) {
00862       AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
00863    } else {
00864       struct extension *exten_iter;
00865 
00866       AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) {
00867          if (exten->index < exten_iter->index) {
00868             AST_LIST_INSERT_BEFORE_CURRENT(exten, entry);
00869          } else if (exten->index == exten_iter->index) {
00870             ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
00871             return -1;
00872          } else if (!AST_LIST_NEXT(exten_iter, entry)) {
00873             AST_LIST_INSERT_TAIL(&user->extensions, exten, entry);
00874          }
00875       }
00876       AST_LIST_TRAVERSE_SAFE_END;
00877    }
00878 
00879    return 0;
00880 }

static struct extension* build_extension ( struct ast_config cfg,
const char *  name 
) [static]

Definition at line 694 of file res_phoneprov.c.

References ast_calloc, ast_calloc_with_stringfields, ast_free, AST_LIST_INSERT_TAIL, ast_string_field_set, ast_var_assign(), ast_variable_retrieve(), ast_var_t::entries, exten, PP_LINEKEYS, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.

00695 {
00696    struct extension *exten;
00697    struct ast_var_t *var;
00698    const char *tmp;
00699    int i;
00700 
00701    if (!(exten = ast_calloc_with_stringfields(1, struct extension, 32))) {
00702       return NULL;
00703    }
00704 
00705    ast_string_field_set(exten, name, name);
00706 
00707    if (!(exten->headp = ast_calloc(1, sizeof(*exten->headp)))) {
00708       ast_free(exten);
00709       exten = NULL;
00710       return NULL;
00711    }
00712 
00713    for (i = 0; i < PP_VAR_LIST_LENGTH; i++) {
00714       tmp = ast_variable_retrieve(cfg, name, pp_variable_list[i].user_var);
00715 
00716       /* If we didn't get a USERNAME variable, set it to the user->name */
00717       if (i == PP_USERNAME && !tmp) {
00718          if ((var = ast_var_assign(pp_variable_list[PP_USERNAME].template_var, exten->name))) {
00719             AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00720          }
00721          continue;
00722       } else if (i == PP_TIMEZONE) {
00723          /* perfectly ok if tmp is NULL, will set variables based on server's time zone */
00724          set_timezone_variables(exten->headp, tmp);
00725       } else if (i == PP_LINENUMBER) {
00726          if (!tmp) {
00727             tmp = "1";
00728          }
00729          exten->index = atoi(tmp);
00730       } else if (i == PP_LINEKEYS) {
00731          if (!tmp) {
00732             tmp = "1";
00733          }
00734       }
00735 
00736       if (tmp && (var = ast_var_assign(pp_variable_list[i].template_var, tmp))) {
00737          AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00738       }
00739    }
00740 
00741    if (!ast_strlen_zero(global_server)) {
00742       if ((var = ast_var_assign("SERVER", global_server)))
00743          AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00744    }
00745 
00746    if (!ast_strlen_zero(global_serverport)) {
00747       if ((var = ast_var_assign("SERVER_PORT", global_serverport)))
00748          AST_LIST_INSERT_TAIL(exten->headp, var, entries);
00749    }
00750 
00751    return exten;
00752 }

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.

Parameters:
name the name of the profile
v ast_variable from parsing phoneprov.conf

Definition at line 572 of file res_phoneprov.c.

References ao2_alloc, args, 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.

00573 {
00574    struct phone_profile *profile;
00575    struct ast_var_t *var;
00576 
00577    if (!(profile = ao2_alloc(sizeof(*profile), profile_destructor))) {
00578       return;
00579    }
00580 
00581    if (ast_string_field_init(profile, 32)) {
00582       profile = unref_profile(profile);
00583       return;
00584    }
00585 
00586    if (!(profile->headp = ast_calloc(1, sizeof(*profile->headp)))) {
00587       profile = unref_profile(profile);
00588       return;
00589    }
00590 
00591    AST_LIST_HEAD_INIT_NOLOCK(&profile->static_files);
00592    AST_LIST_HEAD_INIT_NOLOCK(&profile->dynamic_files);
00593 
00594    ast_string_field_set(profile, name, name);
00595    for (; v; v = v->next) {
00596       if (!strcasecmp(v->name, "mime_type")) {
00597          ast_string_field_set(profile, default_mime_type, v->value);
00598       } else if (!strcasecmp(v->name, "setvar")) {
00599          struct ast_var_t *variable;
00600          char *value_copy = ast_strdupa(v->value);
00601 
00602          AST_DECLARE_APP_ARGS(args,
00603             AST_APP_ARG(varname);
00604             AST_APP_ARG(varval);
00605          );
00606 
00607          AST_NONSTANDARD_APP_ARGS(args, value_copy, '=');
00608          do {
00609             if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
00610                break;
00611             args.varname = ast_strip(args.varname);
00612             args.varval = ast_strip(args.varval);
00613             if (ast_strlen_zero(args.varname) || ast_strlen_zero(args.varval))
00614                break;
00615             if ((variable = ast_var_assign(args.varname, args.varval)))
00616                AST_LIST_INSERT_TAIL(profile->headp, variable, entries);
00617          } while (0);
00618       } else if (!strcasecmp(v->name, "staticdir")) {
00619          ast_string_field_set(profile, staticdir, v->value);
00620       } else {
00621          struct phoneprov_file *pp_file;
00622          char *file_extension;
00623          char *value_copy = ast_strdupa(v->value);
00624 
00625          AST_DECLARE_APP_ARGS(args,
00626             AST_APP_ARG(filename);
00627             AST_APP_ARG(mimetype);
00628          );
00629 
00630          if (!(pp_file = ast_calloc_with_stringfields(1, struct phoneprov_file, 32))) {
00631             profile = unref_profile(profile);
00632             return;
00633          }
00634 
00635          if ((file_extension = strrchr(pp_file->format, '.')))
00636             file_extension++;
00637 
00638          AST_STANDARD_APP_ARGS(args, value_copy);
00639 
00640          /* Mime type order of preference
00641           * 1) Specific mime-type defined for file in profile
00642           * 2) Mime determined by extension
00643           * 3) Default mime type specified in profile
00644           * 4) text/plain
00645           */
00646          ast_string_field_set(pp_file, mime_type, S_OR(args.mimetype,
00647             (S_OR(S_OR(ast_http_ftype2mtype(file_extension), profile->default_mime_type), "text/plain"))));
00648 
00649          if (!strcasecmp(v->name, "static_file")) {
00650             ast_string_field_set(pp_file, format, args.filename);
00651             ast_string_field_build(pp_file, template, "%s%s", profile->staticdir, args.filename);
00652             AST_LIST_INSERT_TAIL(&profile->static_files, pp_file, entry);
00653             /* Add a route for the static files, as their filenames won't change per-user */
00654             build_route(pp_file, NULL, NULL);
00655          } else {
00656             ast_string_field_set(pp_file, format, v->name);
00657             ast_string_field_set(pp_file, template, args.filename);
00658             AST_LIST_INSERT_TAIL(&profile->dynamic_files, pp_file, entry);
00659          }
00660       }
00661    }
00662 
00663    /* Append the global variables to the variables list for this profile.
00664     * This is for convenience later, when we need to provide a single
00665     * variable list for use in substitution. */
00666    ast_mutex_lock(&globals_lock);
00667    AST_LIST_TRAVERSE(&global_variables, var, entries) {
00668       struct ast_var_t *new_var;
00669       if ((new_var = ast_var_assign(var->name, var->value))) {
00670          AST_LIST_INSERT_TAIL(profile->headp, new_var, entries);
00671       }
00672    }
00673    ast_mutex_unlock(&globals_lock);
00674 
00675    ao2_link(profiles, profile);
00676 
00677    profile = unref_profile(profile);
00678 }

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.

Parameters:
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 545 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.

00546 {
00547    struct http_route *route;
00548 
00549    if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
00550       return;
00551    }
00552 
00553    if (ast_string_field_init(route, 32)) {
00554       ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
00555       route = unref_route(route);
00556       return;
00557    }
00558 
00559    ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
00560    route->user = user;
00561    route->file = pp_file;
00562 
00563    ao2_link(http_routes, route);
00564 
00565    route = unref_route(route);
00566 }

static struct user* build_user ( const char *  mac,
struct phone_profile profile 
) [static]

Build and return a user structure based on gathered config data.

Definition at line 817 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().

00818 {
00819    struct user *user;
00820 
00821    if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
00822       profile = unref_profile(profile);
00823       return NULL;
00824    }
00825 
00826    if (ast_string_field_init(user, 32)) {
00827       profile = unref_profile(profile);
00828       user = unref_user(user);
00829       return NULL;
00830    }
00831 
00832    ast_string_field_set(user, macaddress, mac);
00833    user->profile = profile; /* already ref counted by find_profile */
00834 
00835    return user;
00836 }

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 883 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(), phoneprov_file::entry, phoneprov_file::format, str, and user.

00884 {
00885    struct phoneprov_file *pp_file;
00886    struct ast_str *str;
00887 
00888    if (!(str = ast_str_create(16))) {
00889       return -1;
00890    }
00891 
00892    AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
00893       ast_str_substitute_variables_varshead(&str, 0, AST_LIST_FIRST(&user->extensions)->headp, pp_file->format);
00894       build_route(pp_file, user, ast_str_buffer(str));
00895    }
00896 
00897    ast_free(str);
00898    return 0;
00899 }

static struct extension* delete_extension ( struct extension exten  )  [static]

Definition at line 680 of file res_phoneprov.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), ast_var_t::entries, exten, and var.

Referenced by user_destructor().

00681 {
00682    struct ast_var_t *var;
00683    while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) {
00684       ast_var_delete(var);
00685    }
00686    ast_free(exten->headp);
00687    ast_string_field_free_memory(exten);
00688 
00689    ast_free(exten);
00690 
00691    return NULL;
00692 }

static void delete_file ( struct phoneprov_file file  )  [static]

Definition at line 259 of file res_phoneprov.c.

References ast_string_field_free_memory, and free.

Referenced by profile_destructor().

00260 {
00261    ast_string_field_free_memory(file);
00262    free(file);
00263 }

static void delete_profiles ( void   )  [static]

Delete all phone profiles, freeing their memory.

Definition at line 1064 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, profiles, and unref_profile().

Referenced by reload(), and unload_module().

01065 {
01066    struct ao2_iterator i;
01067    struct phone_profile *profile;
01068 
01069    i = ao2_iterator_init(profiles, 0);
01070    while ((profile = ao2_iterator_next(&i))) {
01071       ao2_unlink(profiles, profile);
01072       profile = unref_profile(profile);
01073    }
01074    ao2_iterator_destroy(&i);
01075 }

static void delete_routes ( void   )  [static]

Delete all http routes, freeing their memory.

Definition at line 1050 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, http_routes, and unref_route().

Referenced by reload(), and unload_module().

01051 {
01052    struct ao2_iterator i;
01053    struct http_route *route;
01054 
01055    i = ao2_iterator_init(http_routes, 0);
01056    while ((route = ao2_iterator_next(&i))) {
01057       ao2_unlink(http_routes, route);
01058       route = unref_route(route);
01059    }
01060    ao2_iterator_destroy(&i);
01061 }

static void delete_users ( void   )  [static]

Delete all users.

Definition at line 803 of file res_phoneprov.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, unref_user(), user, and users.

00804 {
00805    struct ao2_iterator i;
00806    struct user *user;
00807 
00808    i = ao2_iterator_init(users, 0);
00809    while ((user = ao2_iterator_next(&i))) {
00810       ao2_unlink(users, user);
00811       user = unref_user(user);
00812    }
00813    ao2_iterator_destroy(&i);
00814 }

static struct phone_profile* find_profile ( const char *  name  )  [static]

Return a phone profile looked up by name.

Definition at line 236 of file res_phoneprov.c.

References ao2_find, phone_profile::name, OBJ_POINTER, and profiles.

00237 {
00238    struct phone_profile tmp = {
00239       .name = name,
00240    };
00241 
00242    return ao2_find(profiles, &tmp, OBJ_POINTER);
00243 }

static struct user* find_user ( const char *  macaddress  )  [static]

Return a user looked up by name.

Definition at line 762 of file res_phoneprov.c.

References ao2_find, user::macaddress, OBJ_POINTER, and users.

00763 {
00764    struct user tmp = {
00765       .macaddress = macaddress,
00766    };
00767 
00768    return ao2_find(users, &tmp, OBJ_POINTER);
00769 }

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 1213 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, http_routes, phoneprov_file::template, unref_route(), http_route::uri, ast_cli_entry::usage, and http_route::user.

01214 {
01215 #define FORMAT "%-40.40s  %-30.30s\n"
01216    struct ao2_iterator i;
01217    struct http_route *route;
01218 
01219    switch(cmd) {
01220    case CLI_INIT:
01221       e->command = "phoneprov show routes";
01222       e->usage =
01223          "Usage: phoneprov show routes\n"
01224          "       Lists all registered phoneprov http routes.\n";
01225       return NULL;
01226    case CLI_GENERATE:
01227       return NULL;
01228    }
01229 
01230    /* This currently iterates over routes twice, but it is the only place I've needed
01231     * to really separate static an dynamic routes, so I've just left it this way. */
01232    ast_cli(a->fd, "Static routes\n\n");
01233    ast_cli(a->fd, FORMAT, "Relative URI", "Physical location");
01234    i = ao2_iterator_init(http_routes, 0);
01235    while ((route = ao2_iterator_next(&i))) {
01236       if (!route->user)
01237          ast_cli(a->fd, FORMAT, route->uri, route->file->template);
01238       route = unref_route(route);
01239    }
01240    ao2_iterator_destroy(&i);
01241 
01242    ast_cli(a->fd, "\nDynamic routes\n\n");
01243    ast_cli(a->fd, FORMAT, "Relative URI", "Template");
01244 
01245    i = ao2_iterator_init(http_routes, 0);
01246    while ((route = ao2_iterator_next(&i))) {
01247       if (route->user)
01248          ast_cli(a->fd, FORMAT, route->uri, route->file->template);
01249       route = unref_route(route);
01250    }
01251    ao2_iterator_destroy(&i);
01252 
01253    return CLI_SUCCESS;
01254 }

static int load_file ( const char *  filename,
char **  ret 
) [static]

Read a TEXT file into a string and return the length.

Definition at line 313 of file res_phoneprov.c.

References ast_malloc, f, free, and len().

Referenced by phoneprov_callback(), and pp_each_extension_helper().

00314 {
00315    int len = 0;
00316    FILE *f;
00317 
00318    if (!(f = fopen(filename, "r"))) {
00319       *ret = NULL;
00320       return -1;
00321    }
00322 
00323    fseek(f, 0, SEEK_END);
00324    len = ftell(f);
00325    fseek(f, 0, SEEK_SET);
00326    if (!(*ret = ast_malloc(len + 1)))
00327       return -2;
00328 
00329    if (len != fread(*ret, sizeof(char), len, f)) {
00330       free(*ret);
00331       *ret = NULL;
00332       return -3;
00333    }
00334 
00335    fclose(f);
00336 
00337    (*ret)[len] = '\0';
00338 
00339    return len;
00340 }

static int load_module ( void   )  [static]

Definition at line 1269 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, globals_lock, http_routes, MAX_PROFILE_BUCKETS, MAX_ROUTE_BUCKETS, MAX_USER_BUCKETS, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profile_cmp_fn(), profile_hash_fn(), profiles, routes_cmp_fn(), routes_hash_fn(), set_config(), users, users_cmp_fn(), and users_hash_fn().

static int lookup_iface ( const char *  iface,
struct in_addr *  address 
) [static]

Definition at line 198 of file res_phoneprov.c.

References ast_copy_string(), ast_log(), errno, LOG_ERROR, and LOG_WARNING.

00199 {
00200    int mysock, res = 0;
00201    struct ifreq ifr;
00202    struct sockaddr_in *sin;
00203 
00204    memset(&ifr, 0, sizeof(ifr));
00205    ast_copy_string(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
00206 
00207    mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
00208    if (mysock < 0) {
00209       ast_log(LOG_ERROR, "Failed to create socket: %s\n", strerror(errno));
00210       return -1;
00211    }
00212 
00213    res = ioctl(mysock, SIOCGIFADDR, &ifr);
00214 
00215    close(mysock);
00216 
00217    if (res < 0) {
00218       ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
00219       memcpy(address, &__ourip, sizeof(__ourip));
00220       return -1;
00221    } else {
00222       sin = (struct sockaddr_in *)&ifr.ifr_addr;
00223       memcpy(address, &sin->sin_addr, sizeof(*address));
00224       return 0;
00225    }
00226 }

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 403 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(), phoneprov_file::entry, user::extensions, ast_tcptls_session_instance::fd, http_route::file, extension::headp, http_routes, 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.

00404 {
00405    struct http_route *route;
00406    struct http_route search_route = {
00407       .uri = uri,
00408    };
00409    struct ast_str *result;
00410    char path[PATH_MAX];
00411    char *file = NULL;
00412    int len;
00413    int fd;
00414    struct ast_str *http_header;
00415 
00416    if (method != AST_HTTP_GET && method != AST_HTTP_HEAD) {
00417       ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
00418       return -1;
00419    }
00420 
00421    if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) {
00422       goto out404;
00423    }
00424 
00425    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
00426 
00427    if (!route->user) { /* Static file */
00428 
00429       fd = open(path, O_RDONLY);
00430       if (fd < 0) {
00431          goto out500;
00432       }
00433 
00434       len = lseek(fd, 0, SEEK_END);
00435       lseek(fd, 0, SEEK_SET);
00436       if (len < 0) {
00437          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00438          close(fd);
00439          goto out500;
00440       }
00441 
00442       http_header = ast_str_create(80);
00443       ast_str_set(&http_header, 0, "Content-type: %s",
00444          route->file->mime_type);
00445 
00446       ast_http_send(ser, method, 200, NULL, http_header, NULL, fd, 0);
00447 
00448       close(fd);
00449       route = unref_route(route);
00450       return 0;
00451    } else { /* Dynamic file */
00452       struct ast_str *tmp;
00453 
00454       len = load_file(path, &file);
00455       if (len < 0) {
00456          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00457          if (file) {
00458             ast_free(file);
00459          }
00460 
00461          goto out500;
00462       }
00463 
00464       if (!file) {
00465          goto out500;
00466       }
00467 
00468       if (!(tmp = ast_str_create(len))) {
00469          if (file) {
00470             ast_free(file);
00471          }
00472 
00473          goto out500;
00474       }
00475 
00476       /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
00477        * the IP address we are listening on that the phone contacted for this config file */
00478       if (ast_strlen_zero(global_server)) {
00479          union {
00480             struct sockaddr sa;
00481             struct sockaddr_in sa_in;
00482          } name;
00483          socklen_t namelen = sizeof(name.sa);
00484          int res;
00485 
00486          if ((res = getsockname(ser->fd, &name.sa, &namelen))) {
00487             ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
00488          } else {
00489             struct ast_var_t *var;
00490             struct extension *exten_iter;
00491 
00492             if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) {
00493                AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
00494                   AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries);
00495                }
00496             }
00497          }
00498       }
00499 
00500       ast_str_substitute_variables_varshead(&tmp, 0, AST_LIST_FIRST(&route->user->extensions)->headp, file);
00501 
00502       if (file) {
00503          ast_free(file);
00504       }
00505 
00506       http_header = ast_str_create(80);
00507       ast_str_set(&http_header, 0, "Content-type: %s",
00508          route->file->mime_type);
00509 
00510       if (!(result = ast_str_create(512))) {
00511          ast_log(LOG_ERROR, "Could not create result string!\n");
00512          if (tmp) {
00513             ast_free(tmp);
00514          }
00515          ast_free(http_header);
00516          goto out500;
00517       }
00518       ast_str_append(&result, 0, "%s", ast_str_buffer(tmp)); 
00519 
00520       ast_http_send(ser, method, 200, NULL, http_header, result, 0, 0);
00521       if (tmp) {
00522          ast_free(tmp);
00523       }
00524 
00525       route = unref_route(route);
00526 
00527       return 0;
00528    }
00529 
00530 out404:
00531    ast_http_error(ser, 404, "Not Found", "Nothing to see here.  Move along.");
00532    return -1;
00533 
00534 out500:
00535    route = unref_route(route);
00536    ast_http_error(ser, 500, "Internal Error", "An internal error has occured.");
00537    return -1;
00538 }

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 1135 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, find_user(), load_file(), LOG_WARNING, str, unref_user(), and user.

Referenced by pp_each_extension_read(), and pp_each_extension_read2().

01136 {
01137    struct user *user;
01138    struct extension *exten;
01139    char path[PATH_MAX];
01140    char *file;
01141    int filelen;
01142    struct ast_str *str;
01143    AST_DECLARE_APP_ARGS(args,
01144       AST_APP_ARG(mac);
01145       AST_APP_ARG(template);
01146    );
01147 
01148    AST_STANDARD_APP_ARGS(args, data);
01149 
01150    if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
01151       ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n");
01152       return 0;
01153    }
01154 
01155    if (!(user = find_user(args.mac))) {
01156       ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
01157       return 0;
01158    }
01159 
01160    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
01161    filelen = load_file(path, &file);
01162    if (filelen < 0) {
01163       ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
01164       if (file) {
01165          ast_free(file);
01166       }
01167       return 0;
01168    }
01169 
01170    if (!file) {
01171       return 0;
01172    }
01173 
01174    if (!(str = ast_str_create(filelen))) {
01175       return 0;
01176    }
01177 
01178    AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
01179       ast_str_substitute_variables_varshead(&str, 0, exten->headp, file);
01180       if (buf) {
01181          size_t slen = len;
01182          ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
01183       } else {
01184          ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
01185       }
01186    }
01187 
01188    ast_free(file);
01189    ast_free(str);
01190 
01191    user = unref_user(user);
01192 
01193    return 0;
01194 }

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

Definition at line 1196 of file res_phoneprov.c.

References pp_each_extension_helper().

01197 {
01198    return pp_each_extension_helper(chan, cmd, data, buf, NULL, len);
01199 }

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 1201 of file res_phoneprov.c.

References pp_each_extension_helper().

01202 {
01203    return pp_each_extension_helper(chan, cmd, data, NULL, buf, len);
01204 }

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 1078 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(), str, string, unref_user(), user, and users.

Referenced by pp_each_user_read(), and pp_each_user_read2().

01079 {
01080    char *tmp;
01081    struct ao2_iterator i;
01082    struct user *user;
01083    struct ast_str *str;
01084    AST_DECLARE_APP_ARGS(args,
01085       AST_APP_ARG(string);
01086       AST_APP_ARG(exclude_mac);
01087    );
01088    AST_STANDARD_APP_ARGS(args, data);
01089 
01090    if (!(str = ast_str_create(16))) {
01091       return -1;
01092    }
01093 
01094    /* Fix data by turning %{ into ${ */
01095    while ((tmp = strstr(args.string, "%{")))
01096       *tmp = '$';
01097 
01098    i = ao2_iterator_init(users, 0);
01099    while ((user = ao2_iterator_next(&i))) {
01100       if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
01101          continue;
01102       }
01103       ast_str_substitute_variables_varshead(&str, len, AST_LIST_FIRST(&user->extensions)->headp, args.string);
01104       if (buf) {
01105          size_t slen = len;
01106          ast_build_string(&buf, &slen, "%s", ast_str_buffer(str));
01107       } else {
01108          ast_str_append(bufstr, len, "%s", ast_str_buffer(str));
01109       }
01110       user = unref_user(user);
01111    }
01112    ao2_iterator_destroy(&i);
01113 
01114    ast_free(str);
01115    return 0;
01116 }

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

Definition at line 1118 of file res_phoneprov.c.

References pp_each_user_helper().

01119 {
01120    return pp_each_user_helper(chan, data, buf, NULL, len);
01121 }

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 1123 of file res_phoneprov.c.

References pp_each_user_helper().

01124 {
01125    return pp_each_user_helper(chan, data, NULL, buf, len);
01126 }

static int profile_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 252 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and phone_profile::name.

Referenced by load_module().

00253 {
00254    const struct phone_profile *profile1 = obj, *profile2 = arg;
00255 
00256    return !strcasecmp(profile1->name, profile2->name) ? CMP_MATCH | CMP_STOP : 0;
00257 }

static void profile_destructor ( void *  obj  )  [static]

Definition at line 265 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, phoneprov_file::entry, phone_profile::headp, phone_profile::static_files, and var.

Referenced by build_profile().

00266 {
00267    struct phone_profile *profile = obj;
00268    struct phoneprov_file *file;
00269    struct ast_var_t *var;
00270 
00271    while ((file = AST_LIST_REMOVE_HEAD(&profile->static_files, entry)))
00272       delete_file(file);
00273 
00274    while ((file = AST_LIST_REMOVE_HEAD(&profile->dynamic_files, entry)))
00275       delete_file(file);
00276 
00277    while ((var = AST_LIST_REMOVE_HEAD(profile->headp, entries)))
00278       ast_var_delete(var);
00279 
00280    ast_free(profile->headp);
00281    ast_string_field_free_memory(profile);
00282 }

static int profile_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 245 of file res_phoneprov.c.

References ast_str_case_hash(), and phone_profile::name.

Referenced by load_module().

00246 {
00247    const struct phone_profile *profile = obj;
00248 
00249    return ast_str_case_hash(profile->name);
00250 }

static int reload ( void   )  [static]

Definition at line 1317 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, globals_lock, set_config(), and var.

01318 {
01319    struct ast_var_t *var;
01320 
01321    delete_routes();
01322    delete_users();
01323    delete_profiles();
01324 
01325    ast_mutex_lock(&globals_lock);
01326    while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) {
01327       ast_var_delete(var);
01328    }
01329    ast_mutex_unlock(&globals_lock);
01330 
01331    set_config();
01332 
01333    return 0;
01334 }

static void route_destructor ( void *  obj  )  [static]

Definition at line 305 of file res_phoneprov.c.

References ast_string_field_free_memory.

Referenced by build_route().

00306 {
00307    struct http_route *route = obj;
00308 
00309    ast_string_field_free_memory(route);
00310 }

static int routes_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 298 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and http_route::uri.

Referenced by load_module().

00299 {
00300    const struct http_route *route1 = obj, *route2 = arg;
00301 
00302    return !strcasecmp(route1->uri, route2->uri) ? CMP_MATCH | CMP_STOP : 0;
00303 }

static int routes_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 291 of file res_phoneprov.c.

References ast_str_case_hash(), and http_route::uri.

Referenced by load_module().

00292 {
00293    const struct http_route *route = obj;
00294 
00295    return ast_str_case_hash(route->uri);
00296 }

static int set_config ( void   )  [static]

Definition at line 902 of file res_phoneprov.c.

References ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_var_assign(), ast_variable_browse(), ast_variable_retrieve(), config_flags, CONFIG_STATUS_FILEINVALID, ast_var_t::entries, global_variables, globals_lock, LOG_WARNING, ast_variable::name, ast_variable::next, S_OR, ast_variable::value, and var.

00903 {
00904    struct ast_config *cfg, *phoneprov_cfg;
00905    char *cat;
00906    struct ast_variable *v;
00907    struct ast_flags config_flags = { 0 };
00908    struct ast_var_t *var;
00909 
00910    /* Try to grab the port from sip.conf.  If we don't get it here, we'll set it
00911     * to whatever is set in phoneprov.conf or default to 5060 */
00912    if ((cfg = ast_config_load("sip.conf", config_flags)) && cfg != CONFIG_STATUS_FILEINVALID) {
00913       ast_copy_string(global_serverport, S_OR(ast_variable_retrieve(cfg, "general", "bindport"), "5060"), sizeof(global_serverport));
00914       ast_config_destroy(cfg);
00915    }
00916 
00917    if (!(cfg = ast_config_load("users.conf", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00918       ast_log(LOG_WARNING, "Unable to load users.conf\n");
00919       return 0;
00920    }
00921 
00922    /* Go ahead and load global variables from users.conf so we can append to profiles */
00923    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
00924       if (!strcasecmp(v->name, "vmexten")) {
00925          if ((var = ast_var_assign("VOICEMAIL_EXTEN", v->value))) {
00926             ast_mutex_lock(&globals_lock);
00927             AST_LIST_INSERT_TAIL(&global_variables, var, entries);
00928             ast_mutex_unlock(&globals_lock);
00929          }
00930       }
00931       if (!strcasecmp(v->name, "localextenlength")) {
00932          if ((var = ast_var_assign("EXTENSION_LENGTH", v->value)))
00933             ast_mutex_lock(&globals_lock);
00934             AST_LIST_INSERT_TAIL(&global_variables, var, entries);
00935             ast_mutex_unlock(&globals_lock);
00936       }
00937    }
00938 
00939    if (!(phoneprov_cfg = ast_config_load("phoneprov.conf", config_flags)) || phoneprov_cfg == CONFIG_STATUS_FILEINVALID) {
00940       ast_log(LOG_ERROR, "Unable to load config phoneprov.conf\n");
00941       ast_config_destroy(cfg);
00942       return -1;
00943    }
00944 
00945    cat = NULL;
00946    while ((cat = ast_category_browse(phoneprov_cfg, cat))) {
00947       if (!strcasecmp(cat, "general")) {
00948          for (v = ast_variable_browse(phoneprov_cfg, cat); v; v = v->next) {
00949             if (!strcasecmp(v->name, "serveraddr"))
00950                ast_copy_string(global_server, v->value, sizeof(global_server));
00951             else if (!strcasecmp(v->name, "serveriface")) {
00952                struct in_addr addr;
00953                lookup_iface(v->value, &addr);
00954                ast_copy_string(global_server, ast_inet_ntoa(addr), sizeof(global_server));
00955             } else if (!strcasecmp(v->name, "serverport"))
00956                ast_copy_string(global_serverport, v->value, sizeof(global_serverport));
00957             else if (!strcasecmp(v->name, "default_profile"))
00958                ast_copy_string(global_default_profile, v->value, sizeof(global_default_profile));
00959          }
00960       } else
00961          build_profile(cat, ast_variable_browse(phoneprov_cfg, cat));
00962    }
00963 
00964    ast_config_destroy(phoneprov_cfg);
00965 
00966    cat = NULL;
00967    while ((cat = ast_category_browse(cfg, cat))) {
00968       const char *tmp, *mac;
00969       struct user *user;
00970       struct phone_profile *profile;
00971       struct extension *exten;
00972 
00973       if (!strcasecmp(cat, "general")) {
00974          continue;
00975       }
00976 
00977       if (!strcasecmp(cat, "authentication"))
00978          continue;
00979 
00980       if (!((tmp = ast_variable_retrieve(cfg, cat, "autoprov")) && ast_true(tmp)))
00981          continue;
00982 
00983       if (!(mac = ast_variable_retrieve(cfg, cat, "macaddress"))) {
00984          ast_log(LOG_WARNING, "autoprov set for %s, but no mac address - skipping.\n", cat);
00985          continue;
00986       }
00987 
00988       tmp = S_OR(ast_variable_retrieve(cfg, cat, "profile"), global_default_profile);
00989       if (ast_strlen_zero(tmp)) {
00990          ast_log(LOG_WARNING, "No profile for user [%s] with mac '%s' - skipping\n", cat, mac);
00991          continue;
00992       }
00993 
00994       if (!(user = find_user(mac))) {
00995          if (!(profile = find_profile(tmp))) {
00996             ast_log(LOG_WARNING, "Could not look up profile '%s' - skipping.\n", tmp);
00997             continue;
00998          }
00999 
01000          if (!(user = build_user(mac, profile))) {
01001             ast_log(LOG_WARNING, "Could not create user for '%s' - skipping\n", user->macaddress);
01002             continue;
01003          }
01004 
01005          if (!(exten = build_extension(cfg, cat))) {
01006             ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress);
01007             user = unref_user(user);
01008             continue;
01009          }
01010 
01011          if (add_user_extension(user, exten)) {
01012             ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
01013             user = unref_user(user);
01014             exten = delete_extension(exten);
01015             continue;
01016          }
01017 
01018          if (build_user_routes(user)) {
01019             ast_log(LOG_WARNING, "Could not create http routes for %s - skipping\n", user->macaddress);
01020             user = unref_user(user);
01021             continue;
01022          }
01023 
01024          ao2_link(users, user);
01025          user = unref_user(user);
01026       } else {
01027          if (!(exten = build_extension(cfg, cat))) {
01028             ast_log(LOG_WARNING, "Could not create extension for %s - skipping\n", user->macaddress);
01029             user = unref_user(user);
01030             continue;
01031          }
01032 
01033          if (add_user_extension(user, exten)) {
01034             ast_log(LOG_WARNING, "Could not add extension '%s' to user '%s'\n", exten->name, user->macaddress);
01035             user = unref_user(user);
01036             exten = delete_extension(exten);
01037             continue;
01038          }
01039 
01040          user = unref_user(user);
01041       }
01042    }
01043 
01044    ast_config_destroy(cfg);
01045 
01046    return 0;
01047 }

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).

Parameters:
headp pointer to list of user variables
zone A time zone. NULL sets variables based on timezone of the machine

Definition at line 346 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().

00347 {
00348    time_t utc_time;
00349    int dstenable;
00350    time_t dststart;
00351    time_t dstend;
00352    struct ast_tm tm_info;
00353    int tzoffset;
00354    char buffer[21];
00355    struct ast_var_t *var;
00356    struct timeval when;
00357 
00358    time(&utc_time);
00359    ast_get_dst_info(&utc_time, &dstenable, &dststart, &dstend, &tzoffset, zone);
00360    snprintf(buffer, sizeof(buffer), "%d", tzoffset);
00361    var = ast_var_assign("TZOFFSET", buffer);
00362    if (var)
00363       AST_LIST_INSERT_TAIL(headp, var, entries);
00364 
00365    if (!dstenable)
00366       return;
00367 
00368    if ((var = ast_var_assign("DST_ENABLE", "1")))
00369       AST_LIST_INSERT_TAIL(headp, var, entries);
00370 
00371    when.tv_sec = dststart;
00372    ast_localtime(&when, &tm_info, zone);
00373 
00374    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon+1);
00375    if ((var = ast_var_assign("DST_START_MONTH", buffer)))
00376       AST_LIST_INSERT_TAIL(headp, var, entries);
00377 
00378    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
00379    if ((var = ast_var_assign("DST_START_MDAY", buffer)))
00380       AST_LIST_INSERT_TAIL(headp, var, entries);
00381 
00382    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
00383    if ((var = ast_var_assign("DST_START_HOUR", buffer)))
00384       AST_LIST_INSERT_TAIL(headp, var, entries);
00385 
00386    when.tv_sec = dstend;
00387    ast_localtime(&when, &tm_info, zone);
00388 
00389    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mon + 1);
00390    if ((var = ast_var_assign("DST_END_MONTH", buffer)))
00391       AST_LIST_INSERT_TAIL(headp, var, entries);
00392 
00393    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_mday);
00394    if ((var = ast_var_assign("DST_END_MDAY", buffer)))
00395       AST_LIST_INSERT_TAIL(headp, var, entries);
00396 
00397    snprintf(buffer, sizeof(buffer), "%d", tm_info.tm_hour);
00398    if ((var = ast_var_assign("DST_END_HOUR", buffer)))
00399       AST_LIST_INSERT_TAIL(headp, var, entries);
00400 }

static int unload_module ( void   )  [static]

Definition at line 1290 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, globals_lock, http_routes, phoneprovuri, pp_cli, pp_each_extension_function, pp_each_user_function, profiles, users, and var.

static struct phone_profile* unref_profile ( struct phone_profile prof  )  [static]

Definition at line 228 of file res_phoneprov.c.

References ao2_ref.

Referenced by build_profile(), build_user(), delete_profiles(), and user_destructor().

00229 {
00230    ao2_ref(prof, -1);
00231 
00232    return NULL;
00233 }

static struct http_route* unref_route ( struct http_route route  )  [static]

Definition at line 284 of file res_phoneprov.c.

References ao2_ref.

Referenced by build_route(), delete_routes(), handle_show_routes(), and phoneprov_callback().

00285 {
00286    ao2_ref(route, -1);
00287 
00288    return NULL;
00289 }

static struct user* unref_user ( struct user user  )  [static]

Definition at line 754 of file res_phoneprov.c.

References ao2_ref, and user.

Referenced by build_user(), delete_users(), pp_each_extension_helper(), and pp_each_user_helper().

00755 {
00756    ao2_ref(user, -1);
00757 
00758    return NULL;
00759 }

static void user_destructor ( void *  obj  )  [static]

Free all memory associated with a user.

Definition at line 786 of file res_phoneprov.c.

References AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, delete_extension(), phoneprov_file::entry, exten, unref_profile(), and user.

00787 {
00788    struct user *user = obj;
00789    struct extension *exten;
00790 
00791    while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
00792       exten = delete_extension(exten);
00793    }
00794 
00795    if (user->profile) {
00796       user->profile = unref_profile(user->profile);
00797    }
00798 
00799    ast_string_field_free_memory(user);
00800 }

static int users_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 778 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and user::macaddress.

Referenced by load_module().

00779 {
00780    const struct user *user1 = obj, *user2 = arg;
00781 
00782    return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0;
00783 }

static int users_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 771 of file res_phoneprov.c.

References ast_str_case_hash(), and user.

Referenced by load_module().

00772 {
00773    const struct user *user = obj;
00774 
00775    return ast_str_case_hash(user->macaddress);
00776 }


Variable Documentation

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1340 of file res_phoneprov.c.

struct in_addr __ourip = { .s_addr = 0x00000000, } [static]

for use in lookup_iface

Definition at line 100 of file res_phoneprov.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1340 of file res_phoneprov.c.

char global_default_profile[80] = "" [static]

Default profile to use if one isn't specified

Definition at line 191 of file res_phoneprov.c.

char global_server[80] = "" [static]

Server to substitute into templates

Definition at line 189 of file res_phoneprov.c.

char global_serverport[6] = "" [static]

Server port to substitute into templates

Definition at line 190 of file res_phoneprov.c.

struct varshead global_variables [static]

List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.

Definition at line 194 of file res_phoneprov.c.

Referenced by load_module(), reload(), set_config(), and unload_module().

ast_mutex_t globals_lock [static]

Definition at line 195 of file res_phoneprov.c.

struct ao2_container* http_routes [static]

Definition at line 186 of file res_phoneprov.c.

Referenced by build_route(), delete_routes(), handle_show_routes(), load_module(), phoneprov_callback(), and unload_module().

struct ast_http_uri phoneprovuri [static]

Definition at line 1260 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry pp_cli[] [static]

Initial value:

 {
   { .handler =  handle_show_routes , .summary =  "Show registered phoneprov http routes" ,__VA_ARGS__ },
}

Definition at line 1256 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function pp_each_extension_function [static]

Initial value:

 {
   .name = "PP_EACH_EXTENSION",
   .read = pp_each_extension_read,
   .read2 = pp_each_extension_read2,
}

Definition at line 1206 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function pp_each_user_function [static]

Initial value:

 {
   .name = "PP_EACH_USER",
   .read = pp_each_user_read,
   .read2 = pp_each_user_read2,
}

Definition at line 1128 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

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_extension().

struct ao2_container* profiles [static]

Definition at line 185 of file res_phoneprov.c.

Referenced by delete_profiles(), find_profile(), load_module(), and unload_module().

struct ao2_container* users [static]

Definition at line 187 of file res_phoneprov.c.


Generated on Mon Jun 27 16:51:20 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7