Wed Aug 18 22:34:32 2010

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

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

01074 {
01075    struct ao2_iterator i;
01076    struct phone_profile *profile;
01077 
01078    i = ao2_iterator_init(profiles, 0);
01079    while ((profile = ao2_iterator_next(&i))) {
01080       ao2_unlink(profiles, profile);
01081       profile = unref_profile(profile);
01082    }
01083    ao2_iterator_destroy(&i);
01084 }

static void delete_routes ( void   )  [static]

Delete all http routes, freeing their memory.

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

01060 {
01061    struct ao2_iterator i;
01062    struct http_route *route;
01063    
01064    i = ao2_iterator_init(http_routes, 0);
01065    while ((route = ao2_iterator_next(&i))) {
01066       ao2_unlink(http_routes, route);
01067       route = unref_route(route);
01068    }
01069    ao2_iterator_destroy(&i);
01070 }

static void delete_users ( void   )  [static]

Delete all users.

Definition at line 822 of file res_phoneprov.c.

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

00823 {
00824    struct ao2_iterator i;
00825    struct user *user;
00826 
00827    i = ao2_iterator_init(users, 0);
00828    while ((user = ao2_iterator_next(&i))) {
00829       ao2_unlink(users, user);
00830       user = unref_user(user);
00831    }
00832    ao2_iterator_destroy(&i);
00833 }

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

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

00782 {
00783    struct user tmp = {
00784       .macaddress = macaddress,
00785    };
00786 
00787    return ao2_find(users, &tmp, OBJ_POINTER);
00788 }

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

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

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 1249 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, fwrite, extension::headp, http_routes, len(), load_file(), LOG_WARNING, phoneprov_file::mime_type, name, 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          union {
00498             struct sockaddr sa;
00499             struct sockaddr_in sa_in;
00500          } name;
00501          socklen_t namelen = sizeof(name.sa);
00502          int res;
00503 
00504          if ((res = getsockname(ser->fd, &name.sa, &namelen))) {
00505             ast_log(LOG_WARNING, "Could not get server IP, breakage likely.\n");
00506          } else {
00507             struct ast_var_t *var;
00508             struct extension *exten_iter;
00509 
00510             if ((var = ast_var_assign("SERVER", ast_inet_ntoa(name.sa_in.sin_addr)))) {
00511                AST_LIST_TRAVERSE(&route->user->extensions, exten_iter, entry) {
00512                   AST_LIST_INSERT_TAIL(exten_iter->headp, var, entries);
00513                }
00514             }
00515          }
00516       }
00517 
00518       pbx_substitute_variables_varshead(AST_LIST_FIRST(&route->user->extensions)->headp, file, tmp, bufsize);
00519    
00520       if (file) {
00521          ast_free(file);
00522       }
00523 
00524       ast_str_append(&result, 0,
00525          "Content-Type: %s\r\n"
00526          "Content-length: %d\r\n"
00527          "\r\n"
00528          "%s", route->file->mime_type, (int) strlen(tmp), tmp);
00529 
00530       if (tmp) {
00531          ast_free(tmp);
00532       }
00533 
00534       route = unref_route(route);
00535 
00536       return result;
00537    }
00538 
00539 out404:
00540    *status = 404;
00541    *title = strdup("Not Found");
00542    *contentlength = 0;
00543    return ast_http_error(404, "Not Found", NULL, "Nothing to see here.  Move along.");
00544 
00545 out500:
00546    route = unref_route(route);
00547    *status = 500;
00548    *title = strdup("Internal Server Error");
00549    *contentlength = 0;
00550    return ast_http_error(500, "Internal Error", NULL, "An internal error has occured.");
00551 }

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

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

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

References ao2_iterator_destroy(), 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.

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

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

01298 {
01299    struct ast_var_t *var;
01300 
01301    delete_routes();
01302    delete_users();
01303    delete_profiles();
01304 
01305    ast_mutex_lock(&globals_lock);
01306    while ((var = AST_LIST_REMOVE_HEAD(&global_variables, entries))) {
01307       ast_var_delete(var);
01308    }
01309    ast_mutex_unlock(&globals_lock);
01310 
01311    set_config();
01312 
01313    return 0;
01314 }

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

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

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 1270 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 773 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().

00774 {
00775    ao2_ref(user, -1);
00776 
00777    return NULL;
00778 }

static void user_destructor ( void *  obj  )  [static]

Free all memory associated with a user.

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

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

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

Definition at line 797 of file res_phoneprov.c.

References CMP_MATCH, CMP_STOP, and user::macaddress.

Referenced by load_module().

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

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

Definition at line 790 of file res_phoneprov.c.

References ast_str_hash(), and user.

Referenced by load_module().

00791 {
00792    const struct user *user = obj;
00793    
00794    return ast_str_hash(user->macaddress);
00795 }


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 1320 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 1320 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 1239 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 1235 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function pp_each_extension_function [static]

Definition at line 1181 of file res_phoneprov.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function pp_each_user_function [static]

Definition at line 1116 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 Wed Aug 18 22:34:32 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7