Fri Jul 24 00:41:56 2009

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_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 * 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_strphoneprov_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *vars, struct ast_variable *headers, int *status, char **title, int *contentlength)
 Callback that is executed everytime an http request is received by this module.
static int pp_each_extension_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 A dialplan function that can be used to output a template for each extension attached to a user.
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_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_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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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
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_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 65 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_ROUTE_BUCKETS   563

Definition at line 66 of file res_phoneprov.c.

Referenced by load_module().

#define MAX_USER_BUCKETS   563

Definition at line 67 of file res_phoneprov.c.

#define VAR_BUF_SIZE   4096

Definition at line 70 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_VAR_LIST_LENGTH 

Definition at line 77 of file res_phoneprov.c.

00077                   {
00078    PP_MACADDRESS,
00079    PP_USERNAME,
00080    PP_FULLNAME,
00081    PP_SECRET,
00082    PP_LABEL,
00083    PP_CALLERID,
00084    PP_TIMEZONE,
00085    PP_LINENUMBER,
00086    PP_VAR_LIST_LENGTH,  /* This entry must always be the last in the list */
00087 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1311 of file res_phoneprov.c.

static void __unreg_module ( void   )  [static]

Definition at line 1311 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 855 of file res_phoneprov.c.

References 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_var_assign(), ast_var_t::entries, phoneprov_file::entry, exten, extension::index, LOG_WARNING, pbx_substitute_variables_varshead(), user, var, and VAR_BUF_SIZE.

00856 {
00857    struct ast_var_t *var;
00858 
00859    /* Append profile variables here, and substitute variables on profile
00860     * setvars, so that we can use user specific variables in them */
00861    AST_LIST_TRAVERSE(user->profile->headp, var, entries) {
00862       char expand_buf[VAR_BUF_SIZE] = {0,};
00863       struct ast_var_t *var2;
00864 
00865       pbx_substitute_variables_varshead(exten->headp, var->value, expand_buf, sizeof(expand_buf));
00866       if ((var2 = ast_var_assign(var->name, expand_buf)))
00867          AST_LIST_INSERT_TAIL(exten->headp, var2, entries);
00868    }
00869 
00870    if (AST_LIST_EMPTY(&user->extensions)) {
00871       AST_LIST_INSERT_HEAD(&user->extensions, exten, entry);
00872    } else {
00873       struct extension *exten_iter;
00874 
00875       AST_LIST_TRAVERSE_SAFE_BEGIN(&user->extensions, exten_iter, entry) {
00876          if (exten->index < exten_iter->index) {
00877             AST_LIST_INSERT_BEFORE_CURRENT(exten, entry);
00878          } else if (exten->index == exten_iter->index) {
00879             ast_log(LOG_WARNING, "Duplicate linenumber=%d for %s\n", exten->index, user->macaddress);
00880             return -1;
00881          } else if (!AST_LIST_NEXT(exten_iter, entry)) {
00882             AST_LIST_INSERT_TAIL(&user->extensions, exten, entry);
00883          }
00884       }
00885       AST_LIST_TRAVERSE_SAFE_END;
00886    }
00887 
00888    return 0;
00889 }

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

Definition at line 708 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(), ast_var_t::entries, exten, PP_LINENUMBER, PP_TIMEZONE, PP_USERNAME, PP_VAR_LIST_LENGTH, pp_variable_list, set_timezone_variables(), and var.

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

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

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

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

00556 {
00557    struct http_route *route;
00558    
00559    if (!(route = ao2_alloc(sizeof(*route), route_destructor))) {
00560       return;
00561    }
00562 
00563    if (ast_string_field_init(route, 32)) {
00564       ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", pp_file->format);
00565       route = unref_route(route);
00566       return;
00567    }
00568 
00569    ast_string_field_set(route, uri, S_OR(uri, pp_file->format));
00570    route->user = user;
00571    route->file = pp_file;
00572 
00573    ao2_link(http_routes, route);
00574 
00575    route = unref_route(route);
00576 }

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

00833 {
00834    struct user *user;
00835 
00836       
00837    if (!(user = ao2_alloc(sizeof(*user), user_destructor))) {
00838       profile = unref_profile(profile);
00839       return NULL;
00840    }
00841    
00842    if (ast_string_field_init(user, 32)) {
00843       profile = unref_profile(profile);
00844       user = unref_user(user);
00845       return NULL;
00846    }
00847 
00848    ast_string_field_set(user, macaddress, mac);
00849    user->profile = profile; /* already ref counted by find_profile */
00850 
00851    return user;
00852 }

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

References AST_LIST_FIRST, AST_LIST_TRAVERSE, build_route(), phoneprov_file::entry, phoneprov_file::format, pbx_substitute_variables_varshead(), user, and VAR_BUF_SIZE.

00893 {
00894    struct phoneprov_file *pp_file;
00895 
00896    AST_LIST_TRAVERSE(&user->profile->dynamic_files, pp_file, entry) {
00897       char expand_buf[VAR_BUF_SIZE] = { 0, };
00898 
00899       pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, pp_file->format, expand_buf, sizeof(expand_buf));
00900       build_route(pp_file, user, expand_buf);
00901    }
00902 
00903    return 0;
00904 }

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

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

00695 {
00696    struct ast_var_t *var;
00697    while ((var = AST_LIST_REMOVE_HEAD(exten->headp, entries))) {
00698       ast_var_delete(var);
00699    }
00700    ast_free(exten->headp);
00701    ast_string_field_free_memory(exten);
00702 
00703    ast_free(exten);
00704 
00705    return NULL;
00706 }

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

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

Referenced by reload(), and unload_module().

01069 {
01070    struct ao2_iterator i;
01071    struct phone_profile *profile;
01072 
01073    i = ao2_iterator_init(profiles, 0);
01074    while ((profile = ao2_iterator_next(&i))) {
01075       ao2_unlink(profiles, profile);
01076       profile = unref_profile(profile);
01077    }
01078 }

static void delete_routes ( void   )  [static]

Delete all http routes, freeing their memory.

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

01056 {
01057    struct ao2_iterator i;
01058    struct http_route *route;
01059    
01060    i = ao2_iterator_init(http_routes, 0);
01061    while ((route = ao2_iterator_next(&i))) {
01062       ao2_unlink(http_routes, route);
01063       route = unref_route(route);
01064    }
01065 }

static void delete_users ( void   )  [static]

Delete all users.

Definition at line 819 of file res_phoneprov.c.

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

00820 {
00821    struct ao2_iterator i;
00822    struct user *user;
00823 
00824    i = ao2_iterator_init(users, 0);
00825    while ((user = ao2_iterator_next(&i))) {
00826       ao2_unlink(users, user);
00827       user = unref_user(user);
00828    }
00829 }

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

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

00779 {
00780    struct user tmp = {
00781       .macaddress = macaddress,
00782    };
00783 
00784    return ao2_find(users, &tmp, OBJ_POINTER);
00785 }

static char* ftype2mtype ( const char *  ftype  )  [static]

Return mime type based on extension.

Definition at line 182 of file res_phoneprov.c.

References ARRAY_LEN, ast_strlen_zero(), ext, and mimetypes.

00183 {
00184    int x;
00185 
00186    if (ast_strlen_zero(ftype))
00187       return NULL;
00188 
00189    for (x = 0;x < ARRAY_LEN(mimetypes);x++) {
00190       if (!strcasecmp(ftype, mimetypes[x].ext))
00191          return mimetypes[x].mtype;
00192    }
00193    
00194    return NULL;
00195 }

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

01186 {
01187 #define FORMAT "%-40.40s  %-30.30s\n"
01188    struct ao2_iterator i;
01189    struct http_route *route;
01190    
01191    switch(cmd) {
01192    case CLI_INIT:
01193       e->command = "phoneprov show routes";
01194       e->usage =
01195          "Usage: phoneprov show routes\n"
01196          "       Lists all registered phoneprov http routes.\n";
01197       return NULL;
01198    case CLI_GENERATE:
01199       return NULL;
01200    }
01201 
01202    /* This currently iterates over routes twice, but it is the only place I've needed
01203     * to really separate static an dynamic routes, so I've just left it this way. */
01204    ast_cli(a->fd, "Static routes\n\n");
01205    ast_cli(a->fd, FORMAT, "Relative URI", "Physical location");
01206    i = ao2_iterator_init(http_routes, 0);
01207    while ((route = ao2_iterator_next(&i))) {
01208       if (!route->user)
01209          ast_cli(a->fd, FORMAT, route->uri, route->file->template);
01210       route = unref_route(route);
01211    }
01212 
01213    ast_cli(a->fd, "\nDynamic routes\n\n");
01214    ast_cli(a->fd, FORMAT, "Relative URI", "Template");
01215 
01216    i = ao2_iterator_init(http_routes, 0);
01217    while ((route = ao2_iterator_next(&i))) {
01218       if (route->user)
01219          ast_cli(a->fd, FORMAT, route->uri, route->file->template);
01220       route = unref_route(route);
01221    }
01222 
01223    return CLI_SUCCESS;
01224 }

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

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 1240 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, 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 struct ast_str* 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 vars,
struct ast_variable headers,
int *  status,
char **  title,
int *  contentlength 
) [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_calloc, ast_config_AST_DATA_DIR, ast_debug, ast_free, ast_get_version(), ast_http_error(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_localtime(), ast_log(), ast_str_append(), ast_str_create(), ast_strftime(), ast_strlen_zero(), ast_tvnow(), ast_var_assign(), buf, phoneprov_file::entry, errno, user::extensions, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, http_route::file, extension::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.

00404 {
00405    struct http_route *route;
00406    struct http_route search_route = {
00407       .uri = uri,
00408    };
00409    struct ast_str *result = ast_str_create(512);
00410    char path[PATH_MAX];
00411    char *file = NULL;
00412    int len;
00413    int fd;
00414    char buf[256];
00415    struct timeval now = ast_tvnow();
00416    struct ast_tm tm;
00417 
00418    if (!(route = ao2_find(http_routes, &search_route, OBJ_POINTER))) {
00419       goto out404;
00420    }
00421 
00422    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, route->file->template);
00423 
00424    if (!route->user) { /* Static file */
00425 
00426       fd = open(path, O_RDONLY);
00427       if (fd < 0) {
00428          goto out500;
00429       }
00430 
00431       len = lseek(fd, 0, SEEK_END);
00432       lseek(fd, 0, SEEK_SET);
00433       if (len < 0) {
00434          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00435          close(fd);
00436          goto out500;
00437       }
00438 
00439       ast_strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %Z", ast_localtime(&now, &tm, "GMT"));
00440       fprintf(ser->f, "HTTP/1.1 200 OK\r\n"
00441          "Server: Asterisk/%s\r\n"
00442          "Date: %s\r\n"
00443          "Connection: close\r\n"
00444          "Cache-Control: no-cache, no-store\r\n"
00445          "Content-Length: %d\r\n"
00446          "Content-Type: %s\r\n\r\n",
00447          ast_get_version(), buf, len, route->file->mime_type);
00448       
00449       while ((len = read(fd, buf, sizeof(buf))) > 0) {
00450          if (fwrite(buf, 1, len, ser->f) != len) {
00451             if (errno != EPIPE) {
00452                ast_log(LOG_WARNING, "fwrite() failed: %s\n", strerror(errno));
00453             } else {
00454                ast_debug(3, "Requester closed the connection while downloading '%s'\n", path);
00455             }
00456             break;
00457          }
00458       }
00459 
00460       close(fd);
00461       route = unref_route(route);
00462       return NULL;
00463    } else { /* Dynamic file */
00464       int bufsize;
00465       char *tmp;
00466 
00467       len = load_file(path, &file);
00468       if (len < 0) {
00469          ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, len);
00470          if (file) {
00471             ast_free(file);
00472          }
00473 
00474          goto out500;
00475       }
00476 
00477       if (!file) {
00478          goto out500;
00479       }
00480 
00481       /* XXX This is a hack -- maybe sum length of all variables in route->user->headp and add that? */
00482       bufsize = len + VAR_BUF_SIZE;
00483       
00484       /* malloc() instead of alloca() here, just in case the file is bigger than
00485        * we have enough stack space for. */
00486       if (!(tmp = ast_calloc(1, bufsize))) {
00487          if (file) {
00488             ast_free(file);
00489          }
00490 
00491          goto out500;
00492       }
00493 
00494       /* Unless we are overridden by serveriface or serveraddr, we set the SERVER variable to
00495        * the IP address we are listening on that the phone contacted for this config file */
00496       if (ast_strlen_zero(global_server)) {
00497          struct sockaddr name;
00498          socklen_t namelen = sizeof(name);
00499          int res;
00500 
00501          if ((res = getsockname(ser->fd, &name, &namelen))) {
00502             ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
00503          } else {
00504             struct ast_var_t *var;
00505             struct extension *exten_iter;
00506 
00507             if ((var = ast_var_assign("SERVER", ast_inet_ntoa(((struct sockaddr_in *)&name)->sin_addr)))) {
00508                AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
00509                   AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries);
00510                }
00511             }
00512          }
00513       }
00514 
00515       pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize);
00516    
00517       if (file) {
00518          ast_free(file);
00519       }
00520 
00521       ast_str_append(&result, 0,
00522          "Content-Type: %s\r\n"
00523          "Content-length: %d\r\n"
00524          "\r\n"
00525          "%s", route->file->mime_type, (int) strlen(tmp), tmp);
00526 
00527       if (tmp) {
00528          ast_free(tmp);
00529       }
00530 
00531       route = unref_route(route);
00532 
00533       return result;
00534    }
00535 
00536 out404:
00537    *status = 404;
00538    *title = strdup("Not Found");
00539    *contentlength = 0;
00540    return ast_http_error(404, "Not Found", NULL, "Nothing to see here.  Move along.");
00541 
00542 out500:
00543    route = unref_route(route);
00544    *status = 500;
00545    *title = strdup("Internal Server Error");
00546    *contentlength = 0;
00547    return ast_http_error(500, "Internal Error", NULL, "An internal error has occured.");
00548 }

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

A dialplan function that can be used to output a template for each extension attached to a user.

Definition at line 1123 of file res_phoneprov.c.

References 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_strlen_zero(), extension::entry, exten, find_user(), load_file(), LOG_WARNING, pbx_substitute_variables_varshead(), unref_user(), user, and VAR_BUF_SIZE.

01124 {
01125    struct user *user;
01126    struct extension *exten;
01127    char path[PATH_MAX];
01128    char *file;
01129    int filelen;
01130    AST_DECLARE_APP_ARGS(args, 
01131       AST_APP_ARG(mac);
01132       AST_APP_ARG(template);
01133    );
01134    
01135    AST_STANDARD_APP_ARGS(args, data);
01136 
01137    if (ast_strlen_zero(args.mac) || ast_strlen_zero(args.template)) {
01138       ast_log(LOG_WARNING, "PP_EACH_EXTENSION requries both a macaddress and template filename.\n");
01139       return 0;
01140    }
01141 
01142    if (!(user = find_user(args.mac))) {
01143       ast_log(LOG_WARNING, "Could not find user with mac = '%s'\n", args.mac);
01144       return 0;
01145    }
01146 
01147    snprintf(path, sizeof(path), "%s/phoneprov/%s", ast_config_AST_DATA_DIR, args.template);
01148    filelen = load_file(path, &file);
01149    if (filelen < 0) {
01150       ast_log(LOG_WARNING, "Could not load file: %s (%d)\n", path, filelen);
01151       if (file) {
01152          ast_free(file);
01153       }
01154       return 0;
01155    }
01156 
01157    if (!file) {
01158       return 0;
01159    }
01160 
01161    AST_LIST_TRAVERSE(&user->extensions, exten, entry) {
01162       char expand_buf[VAR_BUF_SIZE] = {0,};
01163       pbx_substitute_variables_varshead(exten->headp, file, expand_buf, sizeof(expand_buf));
01164       ast_build_string(&buf, &len, "%s", expand_buf);
01165    }
01166 
01167    ast_free(file);
01168 
01169    user = unref_user(user);
01170 
01171    return 0;
01172 }

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

References ao2_iterator_init(), ao2_iterator_next, AST_APP_ARG, ast_build_string(), AST_DECLARE_APP_ARGS, AST_LIST_FIRST, AST_STANDARD_APP_ARGS, ast_strlen_zero(), pbx_substitute_variables_varshead(), unref_user(), user, users, and VAR_BUF_SIZE.

01082 {
01083    char *tmp, expand_buf[VAR_BUF_SIZE] = {0,};
01084    struct ao2_iterator i;
01085    struct user *user;
01086    AST_DECLARE_APP_ARGS(args,
01087       AST_APP_ARG(string);
01088       AST_APP_ARG(exclude_mac);
01089    );
01090    AST_STANDARD_APP_ARGS(args, data);
01091 
01092    /* Fix data by turning %{ into ${ */
01093    while ((tmp = strstr(args.string, "%{")))
01094       *tmp = '$';
01095 
01096    i = ao2_iterator_init(users, 0);
01097    while ((user = ao2_iterator_next(&i))) {
01098       if (!ast_strlen_zero(args.exclude_mac) && !strcasecmp(user->macaddress, args.exclude_mac)) {
01099          continue;
01100       }
01101       pbx_substitute_variables_varshead(AST_LIST_FIRST(&user->extensions)->headp, args.string, expand_buf, sizeof(expand_buf));
01102       ast_build_string(&buf, &len, "%s", expand_buf);
01103       user = unref_user(user);
01104    }
01105 
01106    return 0;
01107 }

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_hash(), and phone_profile::name.

Referenced by load_module().

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

static int reload ( void   )  [static]

Definition at line 1288 of file res_phoneprov.c.

References AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), ast_var_delete(), delete_profiles(), delete_routes(), delete_users(), ast_var_t::entries, global_variables, set_config(), and var.

01289 {
01290    struct ast_var_t *var;
01291 
01292    delete_routes();
01293    delete_users();
01294    delete_profiles();
01295 
01296    ast_mutex_lock(&globals_lock);
01297    while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) {
01298       ast_var_delete(var);
01299    }
01300    ast_mutex_unlock(&globals_lock);
01301 
01302    set_config();
01303 
01304    return 0;
01305 }

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 !strcmp(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_hash(), and http_route::uri.

Referenced by load_module().

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

static int set_config ( void   )  [static]

Definition at line 907 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, ast_var_t::entries, global_variables, LOG_WARNING, ast_variable::name, ast_variable::next, S_OR, ast_variable::value, and var.

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

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 1261 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, 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 770 of file res_phoneprov.c.

References ao2_ref, and user.

Referenced by build_user(), delete_users(), pp_each_extension_exec(), and pp_each_user_exec().

00771 {
00772    ao2_ref(user, -1);
00773 
00774    return NULL;
00775 }

static void user_destructor ( void *  obj  )  [static]

Free all memory associated with a user.

Definition at line 802 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.

00803 {
00804    struct user *user = obj;
00805    struct extension *exten;
00806 
00807    while ((exten = AST_LIST_REMOVE_HEAD(&user->extensions, entry))) {
00808       exten = delete_extension(exten);
00809    }
00810 
00811    if (user->profile) {
00812       user->profile = unref_profile(user->profile);
00813    }
00814    
00815    ast_string_field_free_memory(user);
00816 }

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

Definition at line 794 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and user::macaddress.

Referenced by load_module().

00795 {
00796    const struct user *user1 = obj, *user2 = arg;
00797 
00798    return !strcasecmp(user1->macaddress, user2->macaddress) ? CMP_MATCH | CMP_STOP : 0;
00799 }

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

Definition at line 787 of file res_phoneprov.c.

References ast_str_hash(), and user.

Referenced by load_module().

00788 {
00789    const struct user *user = obj;
00790    
00791    return ast_str_hash(user->macaddress);
00792 }


Variable Documentation

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

Definition at line 1311 of file res_phoneprov.c.

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

for use in lookup_iface

Definition at line 73 of file res_phoneprov.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1311 of file res_phoneprov.c.

char* ext

Definition at line 162 of file res_phoneprov.c.

char global_default_profile[80] = "" [static]

Default profile to use if one isn't specified

Definition at line 175 of file res_phoneprov.c.

char global_server[80] = "" [static]

Server to substitute into templates

Definition at line 173 of file res_phoneprov.c.

char global_serverport[6] = "" [static]

Server port to substitute into templates

Definition at line 174 of file res_phoneprov.c.

struct varshead global_variables [static]

List of global variables currently available: VOICEMAIL_EXTEN, EXTENSION_LENGTH.

Definition at line 178 of file res_phoneprov.c.

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

ast_mutex_t globals_lock [static]

Definition at line 179 of file res_phoneprov.c.

struct ao2_container* http_routes [static]

Definition at line 157 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 163 of file res_phoneprov.c.

struct ast_http_uri phoneprovuri [static]

Definition at line 1230 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 1226 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function pp_each_extension_function [static]

Definition at line 1174 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function pp_each_user_function [static]

Definition at line 1109 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 156 of file res_phoneprov.c.

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

struct ao2_container* users [static]

Definition at line 158 of file res_phoneprov.c.


Generated on Fri Jul 24 00:41:57 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7