Mon Oct 8 12:39:27 2012

Asterisk developer's documentation


res_calendar.c File Reference

Calendaring API. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/calendar.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/sched.h"
#include "asterisk/dial.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"

Go to the source code of this file.

Data Structures

struct  evententry
struct  eventlist
struct  techs

Defines

#define CALENDAR_BUCKETS   19
#define FORMAT   "%-17.17s : %-20.20s\n"
#define FORMAT   "%-20.20s %-10.10s %-6.6s\n"
#define FORMAT2   "%-12.12s: %-40.60s\n"

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int add_event_to_list (struct eventlist *events, struct ast_calendar_event *event, time_t start, time_t end)
static int add_new_event_cb (void *obj, void *arg, int flags)
void ast_calendar_clear_events (struct ast_calendar *cal)
 Remove all events from calendar.
ast_configast_calendar_config_acquire (void)
 Grab and lock pointer to the calendar config (read only).
void ast_calendar_config_release (void)
 Release the calendar config.
ast_calendar_eventast_calendar_event_alloc (struct ast_calendar *cal)
 Allocate an astobj2 ast_calendar_event object.
ao2_containerast_calendar_event_container_alloc (void)
 Allocate an astobj2 container for ast_calendar_event objects.
void ast_calendar_merge_events (struct ast_calendar *cal, struct ao2_container *new_events)
 Add an event to the list of events for a calendar.
int ast_calendar_register (struct ast_calendar_tech *tech)
 Register a new calendar technology.
ast_calendar_eventast_calendar_unref_event (struct ast_calendar_event *event)
 Unreference an ast_calendar_event.
void ast_calendar_unregister (struct ast_calendar_tech *tech)
 Unregister a new calendar technology.
static struct ast_calendarbuild_calendar (struct ast_config *cfg, const char *cat, const struct ast_calendar_tech *tech)
static int calendar_busy_callback (void *obj, void *arg, int flags)
static int calendar_busy_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 A dialplan function that can be used to determine the busy status of a calendar.
static int calendar_cmp_fn (void *obj, void *arg, int flags)
static void calendar_destructor (void *obj)
static int calendar_devstate_change (const void *data)
static void calendar_event_destructor (void *obj)
static int calendar_event_notify (const void *data)
static int calendar_event_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int calendar_hash_fn (const void *obj, const int flags)
static int calendar_is_busy (struct ast_calendar *cal)
static void calendar_join_attendees (struct ast_calendar_event *event, char *buf, size_t len)
static int calendar_query_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int calendar_query_result_exec (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int calendar_write_exec (struct ast_channel *chan, const char *cmd, char *data, const char *value)
static enum ast_device_state calendarstate (const char *data)
static int cb_pending_deletion (void *user_data, void *arg, int flags)
static int cb_rm_pending_deletion (void *user_data, void *arg, int flags)
static int clear_events_cb (void *user_data, void *arg, int flags)
static void copy_event_data (struct ast_calendar_event *dst, struct ast_calendar_event *src)
static struct ast_calendar_eventdestroy_event (struct ast_calendar_event *event)
static void * do_notify (void *data)
static void * do_refresh (void *data)
static char * epoch_to_string (char *buf, size_t buflen, time_t epoch)
static int event_cmp_fn (void *obj, void *arg, int flags)
static int event_hash_fn (const void *obj, const int flags)
static void event_notification_destroy (void *data)
static void * event_notification_duplicate (void *data)
static void eventlist_destroy (void *data)
static void eventlist_destructor (void *obj)
static void * eventlist_duplicate (void *data)
static struct ast_calendarfind_calendar (const char *name)
static struct ast_calendar_eventfind_event (struct ao2_container *events, const char *uid)
static char * generate_random_string (char *buf, size_t size)
 Generate 32 byte random string (stolen from chan_sip.c).
static char * handle_dump_sched (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_calendar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_show_calendars (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list available calendars.
static int load_config (int reload)
static int load_module (void)
static int load_tech_calendars (struct ast_calendar_tech *tech)
static int match_caltech_cb (void *user_data, void *arg, int flags)
static int merge_events_cb (void *obj, void *arg, int flags)
static int null_chan_write (struct ast_channel *chan, struct ast_frame *frame)
static int reload (void)
static int schedule_calendar_event (struct ast_calendar *cal, struct ast_calendar_event *old_event, struct ast_calendar_event *cmp_event)
static int unload_module (void)
static struct ast_calendarunref_calendar (struct ast_calendar *cal)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk Calendar integration" , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_custom_function calendar_busy_function
static struct ast_cli_entry calendar_cli []
static struct ast_configcalendar_config
static struct ast_custom_function calendar_event_function
static struct ast_custom_function calendar_query_function
static struct ast_custom_function calendar_query_result_function
static struct ast_custom_function calendar_write_function
static struct ao2_containercalendars
static ast_rwlock_t config_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
static struct ast_datastore_info event_notification_datastore
static struct ast_datastore_info eventlist_datastore_info
static int module_unloading
static struct ast_channel_tech null_tech
static ast_cond_t refresh_condition
static pthread_t refresh_thread = AST_PTHREADT_NULL
static ast_mutex_t refreshlock
static ast_mutex_t reloadlock
static struct sched_contextsched


Detailed Description

Calendaring API.

Todo:
Support responding to a meeting invite

Support writing attendees

Definition in file res_calendar.c.


Define Documentation

#define CALENDAR_BUCKETS   19

Definition at line 199 of file res_calendar.c.

Referenced by ast_calendar_event_container_alloc(), build_calendar(), and load_module().

#define FORMAT   "%-17.17s : %-20.20s\n"

#define FORMAT   "%-20.20s %-10.10s %-6.6s\n"

#define FORMAT2   "%-12.12s: %-40.60s\n"


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1786 of file res_calendar.c.

static void __unreg_module ( void   )  [static]

Definition at line 1786 of file res_calendar.c.

static int add_event_to_list ( struct eventlist events,
struct ast_calendar_event event,
time_t  start,
time_t  end 
) [static]

Definition at line 1024 of file res_calendar.c.

References ao2_ref, ast_calloc, ast_debug, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_calendar_event::end, evententry::event, events, evententry::list, LOG_ERROR, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.

Referenced by calendar_query_exec().

01025 {
01026    struct evententry *entry, *iter;
01027    int event_startdiff = abs(start - event->start);
01028    int event_enddiff = abs(end - event->end);
01029    int i = 0;
01030 
01031    if (!(entry = ast_calloc(1, sizeof(*entry)))) {
01032       ast_log(LOG_ERROR, "Unable to allocate memory for event list\n");
01033       return -1;
01034    }
01035 
01036    entry->event = event;
01037    ao2_ref(event, +1);
01038 
01039    if (start == end) {
01040       AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) {
01041          int startdiff = abs(iter->event->start - start);
01042 
01043          ast_debug(10, "Comparing %s with startdiff %d to %s with startdiff %d\n", event->summary, event_startdiff, iter->event->summary, startdiff);
01044          ++i;
01045          if (startdiff > event_startdiff) {
01046             AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
01047             return i;
01048          }
01049          if (startdiff == event_startdiff) {
01050             int enddiff = abs(iter->event->end - end);
01051 
01052             if (enddiff > event_enddiff) {
01053                AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
01054                return i;
01055             }
01056             if (event_startdiff == enddiff) {
01057                if (strcmp(event->uid, iter->event->uid) < 0) {
01058                   AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
01059                   return i;
01060                }
01061             }
01062          }
01063       }
01064       AST_LIST_TRAVERSE_SAFE_END;
01065 
01066       AST_LIST_INSERT_TAIL(events, entry, list);
01067 
01068       return i;
01069    }
01070 
01071    AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) {
01072       ++i;
01073       if (iter->event->start > event->start) {
01074          AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
01075          return i;
01076       }
01077 
01078       if (iter->event->start == event->start) {
01079          if ((iter->event->end - iter->event->start) == (event->end - event->start)) {
01080             if (strcmp(event->uid, iter->event->uid) < 0) {
01081                AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
01082                return i;
01083             }
01084          }
01085          if ((iter->event->end - iter->event->start) < (event->end - event->start)) {
01086             AST_LIST_INSERT_BEFORE_CURRENT(entry, list);
01087             return i;
01088          }
01089       }
01090    }
01091    AST_LIST_TRAVERSE_SAFE_END;
01092 
01093    AST_LIST_INSERT_TAIL(events, entry, list);
01094 
01095    return i;
01096 }

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

Definition at line 948 of file res_calendar.c.

References ao2_link, CMP_MATCH, events, ast_calendar_event::owner, and schedule_calendar_event().

Referenced by ast_calendar_merge_events().

00949 {
00950    struct ast_calendar_event *new_event = obj;
00951    struct ao2_container *events = arg;
00952 
00953    ao2_link(events, new_event);
00954    schedule_calendar_event(new_event->owner, new_event, NULL);
00955    return CMP_MATCH;
00956 }

void ast_calendar_clear_events ( struct ast_calendar cal  ) 

Remove all events from calendar.

Parameters:
cal calendar whose events need to be cleared

Definition at line 596 of file res_calendar.c.

References ao2_callback, ast_debug, clear_events_cb(), ast_calendar::events, ast_calendar::name, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by calendar_destructor().

00597 {
00598    ast_debug(3, "Clearing all events for calendar %s\n", cal->name);
00599 
00600    ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, clear_events_cb, NULL);
00601 }

struct ast_config* ast_calendar_config_acquire ( void   ) 

Grab and lock pointer to the calendar config (read only).

Note:
ast_calendar_config_release must be called when finished with the pointer
Returns:
the parsed calendar config

Definition at line 237 of file res_calendar.c.

References ast_rwlock_rdlock, and ast_rwlock_unlock.

Referenced by caldav_load_calendar(), ewscal_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().

00238 {
00239    ast_rwlock_rdlock(&config_lock);
00240 
00241    if (!calendar_config) {
00242       ast_rwlock_unlock(&config_lock);
00243       return NULL;
00244    }
00245 
00246    return calendar_config;
00247 }

void ast_calendar_config_release ( void   ) 

Release the calendar config.

Definition at line 249 of file res_calendar.c.

References ast_rwlock_unlock, and config_lock.

Referenced by caldav_load_calendar(), ewscal_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().

00250 {
00251    ast_rwlock_unlock(&config_lock);
00252 }

struct ast_calendar_event* ast_calendar_event_alloc ( struct ast_calendar cal  ) 

Allocate an astobj2 ast_calendar_event object.

Parameters:
cal calendar to allocate an event for
Returns:
a new, initialized calendar event

Definition at line 603 of file res_calendar.c.

References ao2_alloc, ast_calendar_unref_event(), AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, and calendar_event_destructor().

Referenced by caldav_add_event(), calendar_write_exec(), icalendar_add_event(), parse_tag(), and startelm().

00604 {
00605    struct ast_calendar_event *event;
00606    if (!(event = ao2_alloc(sizeof(*event), calendar_event_destructor))) {
00607       return NULL;
00608    }
00609 
00610    if (ast_string_field_init(event, 32)) {
00611       event = ast_calendar_unref_event(event);
00612       return NULL;
00613    }
00614 
00615    event->owner = cal;
00616    event->notify_sched = -1;
00617    event->bs_start_sched = -1;
00618    event->bs_end_sched = -1;
00619 
00620    AST_LIST_HEAD_INIT_NOLOCK(&event->attendees);
00621 
00622    return event;
00623 }

struct ao2_container* ast_calendar_event_container_alloc ( void   ) 

Allocate an astobj2 container for ast_calendar_event objects.

Returns:
a new event container

Definition at line 625 of file res_calendar.c.

References ao2_container_alloc, CALENDAR_BUCKETS, event_cmp_fn(), and event_hash_fn().

Referenced by caldav_load_calendar(), ewscal_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().

void ast_calendar_merge_events ( struct ast_calendar cal,
struct ao2_container new_events 
)

Add an event to the list of events for a calendar.

Parameters:
cal calendar containing the events to be merged
new_events an oa2 container of events to be merged into cal->events

Definition at line 958 of file res_calendar.c.

References add_new_event_cb(), ao2_callback, ast_calendar::events, merge_events_cb(), OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by endelm(), icalendar_update_events(), startelm(), update_caldav(), and update_exchangecal().

00959 {
00960    /* Loop through all events attached to the calendar.  If there is a matching new event
00961     * merge its data over and handle any schedule changes that need to be made.  Then remove
00962     * the new_event from new_events so that we are left with only new_events that we can add later. */
00963    ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, merge_events_cb, new_events);
00964 
00965    /* Now, we should only have completely new events in new_events.  Loop through and add them */
00966    ao2_callback(new_events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, add_new_event_cb, cal->events);
00967 }

int ast_calendar_register ( struct ast_calendar_tech tech  ) 

Register a new calendar technology.

Parameters:
tech calendar technology to register
Return values:
0 success
-1 failure

Definition at line 490 of file res_calendar.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_module_user_add, ast_verb, ast_calendar_tech::description, ast_calendar_tech::list, load_tech_calendars(), LOG_WARNING, ast_calendar_tech::type, and ast_calendar_tech::user.

Referenced by load_module().

00491 {
00492    struct ast_calendar_tech *iter;
00493 
00494    AST_LIST_LOCK(&techs);
00495    AST_LIST_TRAVERSE(&techs, iter, list) {
00496       if(!strcasecmp(tech->type, iter->type)) {
00497          ast_log(LOG_WARNING, "Already have a handler for calendar type '%s'\n", tech->type);
00498          AST_LIST_UNLOCK(&techs);
00499          return -1;
00500       }
00501    }
00502    AST_LIST_INSERT_HEAD(&techs, tech, list);
00503    tech->user = ast_module_user_add(NULL);
00504    AST_LIST_UNLOCK(&techs);
00505 
00506    ast_verb(2, "Registered calendar type '%s' (%s)\n", tech->type, tech->description);
00507 
00508    return load_tech_calendars(tech);
00509 }

struct ast_calendar_event* ast_calendar_unref_event ( struct ast_calendar_event event  ) 

Unreference an ast_calendar_event.

Parameters:
event event to unref
Returns:
NULL

Definition at line 300 of file res_calendar.c.

References ao2_ref, and evententry::event.

Referenced by ast_calendar_event_alloc(), caldav_add_event(), calendar_devstate_change(), calendar_query_exec(), do_notify(), endelm(), event_notification_destroy(), handle_show_calendar(), icalendar_add_event(), merge_events_cb(), and parse_tag().

00301 {
00302    ao2_ref(event, -1);
00303    return NULL;
00304 }

void ast_calendar_unregister ( struct ast_calendar_tech tech  ) 

Unregister a new calendar technology.

Parameters:
tech calendar technology to unregister
Return values:
0 success
-1 failure

Definition at line 523 of file res_calendar.c.

References ao2_callback, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module_user_remove, ast_verb, ast_calendar_tech::list, match_caltech_cb(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_calendar_tech::type, and ast_calendar_tech::user.

Referenced by load_tech_calendars(), and unload_module().

00524 {
00525    struct ast_calendar_tech *iter;
00526 
00527    AST_LIST_LOCK(&techs);
00528    AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, iter, list) {
00529       if (iter != tech) {
00530          continue;
00531       }
00532 
00533       ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, match_caltech_cb, tech);
00534 
00535       AST_LIST_REMOVE_CURRENT(list);
00536       ast_module_user_remove(iter->user);
00537       ast_verb(2, "Unregistered calendar type '%s'\n", tech->type);
00538       break;
00539    }
00540    AST_LIST_TRAVERSE_SAFE_END;
00541    AST_LIST_UNLOCK(&techs);
00542 
00543 }

static struct ast_calendar* build_calendar ( struct ast_config cfg,
const char *  cat,
const struct ast_calendar_tech tech 
) [static]

Definition at line 378 of file res_calendar.c.

References ao2_alloc, ao2_container_alloc, ast_log(), ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_calendar::autoreminder, CALENDAR_BUCKETS, calendar_destructor(), event_cmp_fn(), event_hash_fn(), find_calendar(), LOG_ERROR, ast_variable::name, name, ast_variable::next, ast_calendar::notify_waittime, ast_calendar::pending_deletion, ast_calendar::refresh, ast_calendar::tech, ast_calendar::timeframe, unref_calendar(), and ast_variable::value.

Referenced by load_tech_calendars().

00379 {
00380    struct ast_calendar *cal;
00381    struct ast_variable *v;
00382    int new_calendar = 0;
00383 
00384    if (!(cal = find_calendar(cat))) {
00385       new_calendar = 1;
00386       if (!(cal = ao2_alloc(sizeof(*cal), calendar_destructor))) {
00387          ast_log(LOG_ERROR, "Could not allocate calendar structure. Stopping.\n");
00388          return NULL;
00389       }
00390 
00391       if (!(cal->events = ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn))) {
00392          ast_log(LOG_ERROR, "Could not allocate events container for %s\n", cat);
00393          cal = unref_calendar(cal);
00394          return NULL;
00395       }
00396 
00397       if (ast_string_field_init(cal, 32)) {
00398          ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", cat);
00399          cal = unref_calendar(cal);
00400          return NULL;
00401       }
00402    } else {
00403       cal->pending_deletion = 0;
00404    }
00405 
00406    ast_string_field_set(cal, name, cat);
00407    cal->tech = tech;
00408 
00409    cal->refresh = 3600;
00410    cal->timeframe = 60;
00411    cal->notify_waittime = 30000;
00412 
00413    for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
00414       if (!strcasecmp(v->name, "autoreminder")) {
00415          cal->autoreminder = atoi(v->value);
00416       } else if (!strcasecmp(v->name, "channel")) {
00417          ast_string_field_set(cal, notify_channel, v->value);
00418       } else if (!strcasecmp(v->name, "context")) {
00419          ast_string_field_set(cal, notify_context, v->value);
00420       } else if (!strcasecmp(v->name, "extension")) {
00421          ast_string_field_set(cal, notify_extension, v->value);
00422       } else if (!strcasecmp(v->name, "waittime")) {
00423          int i = atoi(v->value);
00424          if (i > 0) {
00425             cal->notify_waittime = 1000 * i;
00426          }
00427       } else if (!strcasecmp(v->name, "app")) {
00428          ast_string_field_set(cal, notify_app, v->value);
00429       } else if (!strcasecmp(v->name, "appdata")) {
00430          ast_string_field_set(cal, notify_appdata, v->value);
00431       } else if (!strcasecmp(v->name, "refresh")) {
00432          cal->refresh = atoi(v->value);
00433       } else if (!strcasecmp(v->name, "timeframe")) {
00434          cal->timeframe = atoi(v->value);
00435       }
00436    }
00437 
00438    if (new_calendar) {
00439       cal->thread = AST_PTHREADT_NULL;
00440       ast_cond_init(&cal->unload, NULL);
00441       ao2_link(calendars, cal);
00442       if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) {
00443          /* If we start failing to create threads, go ahead and return NULL
00444           * and the tech module will be unregistered
00445           */ 
00446          ao2_unlink(calendars, cal);
00447          cal = unref_calendar(cal);
00448       }
00449    }
00450 
00451    return cal;
00452 }

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

Definition at line 336 of file res_calendar.c.

References AST_CALENDAR_BS_FREE, ast_tvnow(), ast_calendar_event::busy_state, CMP_STOP, ast_calendar_event::end, evententry::event, and ast_calendar_event::start.

Referenced by calendar_is_busy().

00337 {
00338    struct ast_calendar_event *event = obj;
00339    int *is_busy = arg;
00340    struct timeval tv = ast_tvnow();
00341 
00342    if (tv.tv_sec >= event->start && tv.tv_sec <= event->end && event->busy_state > AST_CALENDAR_BS_FREE) {
00343       *is_busy = 1;
00344       return CMP_STOP;
00345    }
00346 
00347    return 0;
00348 }

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

A dialplan function that can be used to determine the busy status of a calendar.

Definition at line 997 of file res_calendar.c.

References ast_log(), ast_strlen_zero(), calendar_is_busy(), find_calendar(), LOG_WARNING, and unref_calendar().

00998 {
00999    struct ast_calendar *cal;
01000 
01001    if (ast_strlen_zero(data)) {
01002       ast_log(LOG_WARNING, "CALENDAR_BUSY requires an argument: CALENDAR_BUSY(<calendar_name>)\n");
01003       return -1;
01004    }
01005 
01006    cal = find_calendar(data);
01007 
01008    if (!cal) {
01009       ast_log(LOG_WARNING, "Could not find calendar '%s'\n", data);
01010       return -1;
01011    }
01012 
01013    strcpy(buf, calendar_is_busy(cal) ? "1" : "0");
01014    cal = unref_calendar(cal);
01015 
01016    return 0;
01017 }

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

Definition at line 266 of file res_calendar.c.

References CMP_MATCH, CMP_STOP, and ast_calendar::name.

Referenced by load_module().

00267 {
00268    const struct ast_calendar *one = obj, *two = arg;
00269    return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP: 0;
00270 }

static void calendar_destructor ( void *  obj  )  [static]

Definition at line 306 of file res_calendar.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_calendar_clear_events(), ast_cond_signal, ast_debug, ast_string_field_free_memory, ast_calendar::events, ast_calendar::name, ast_calendar::tech, ast_calendar::tech_pvt, ast_calendar::thread, ast_calendar::unload, ast_calendar::unloading, and ast_calendar_tech::unref_calendar.

Referenced by build_calendar().

00307 {
00308    struct ast_calendar *cal = obj;
00309 
00310    ast_debug(3, "Destroying calendar %s\n", cal->name);
00311 
00312    ao2_lock(cal);
00313    cal->unloading = 1;
00314    ast_cond_signal(&cal->unload);
00315    pthread_join(cal->thread, NULL);
00316    if (cal->tech_pvt) {
00317       cal->tech_pvt = cal->tech->unref_calendar(cal->tech_pvt);
00318    }
00319    ast_calendar_clear_events(cal);
00320    ast_string_field_free_memory(cal);
00321    ao2_ref(cal->events, -1);
00322    ao2_unlock(cal);
00323 }

static int calendar_devstate_change ( const void *  data  )  [static]

Definition at line 797 of file res_calendar.c.

References ao2_ref, ast_calendar_unref_event(), AST_DEVICE_BUSY, AST_DEVICE_NOT_INUSE, ast_devstate_changed(), ast_log(), ast_tvnow(), ast_calendar_event::bs_end_sched, ast_calendar_event::bs_start_sched, calendar_is_busy(), ast_calendar_event::end, LOG_WARNING, ast_calendar::name, and ast_calendar_event::owner.

Referenced by schedule_calendar_event().

00798 {
00799    struct ast_calendar_event *event = (struct ast_calendar_event *)data;
00800    struct timeval now = ast_tvnow();
00801    int is_end_event;
00802 
00803    if (!event) {
00804       ast_log(LOG_WARNING, "Event was NULL!\n");
00805       return 0;
00806    }
00807 
00808    ao2_ref(event, +1);
00809 
00810    is_end_event = event->end <= now.tv_sec;
00811 
00812    if (is_end_event) {
00813       event->bs_end_sched = -1;
00814    } else {
00815       event->bs_start_sched = -1;
00816    }
00817 
00818    /* We can have overlapping events, so ignore the event->busy_state and check busy state
00819     * based on all events in the calendar */
00820    if (!calendar_is_busy(event->owner)) {
00821       ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name);
00822    } else {
00823       ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name);
00824    }
00825 
00826    event = ast_calendar_unref_event(event);
00827 
00828    return 0;
00829 }

static void calendar_event_destructor ( void *  obj  )  [static]

Definition at line 545 of file res_calendar.c.

References ast_debug, ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_calendar_event::attendees, ast_calendar_attendee::data, ast_calendar::name, ast_calendar_attendee::next, and ast_calendar_event::owner.

Referenced by ast_calendar_event_alloc().

00546 {
00547    struct ast_calendar_event *event = obj;
00548    struct ast_calendar_attendee *attendee;
00549 
00550    ast_debug(3, "Destroying event for calendar '%s'\n", event->owner->name);
00551    ast_string_field_free_memory(event);
00552    while ((attendee = AST_LIST_REMOVE_HEAD(&event->attendees, next))) {
00553       if (attendee->data) {
00554          ast_free(attendee->data);
00555       }
00556       ast_free(attendee);
00557    }
00558 }

static int calendar_event_notify ( const void *  data  )  [static]

Definition at line 773 of file res_calendar.c.

References ao2_ref, ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, do_notify(), LOG_ERROR, ast_calendar_event::notify_sched, and ast_calendar_event::owner.

Referenced by schedule_calendar_event().

00774 {
00775    struct ast_calendar_event *event = (void *)data;
00776    int res = -1;
00777    pthread_t notify_thread = AST_PTHREADT_NULL;
00778 
00779    if (!(event && event->owner)) {
00780       ast_log(LOG_ERROR, "Extremely low-cal...in fact cal is NULL!\n");
00781       return res;
00782    }
00783 
00784    ao2_ref(event, +1);
00785    event->notify_sched = -1;
00786 
00787    if (ast_pthread_create_background(&notify_thread, NULL, do_notify, event) < 0) {
00788       ast_log(LOG_ERROR, "Could not create notification thread\n");
00789       return res;
00790    }
00791 
00792    res = 0;
00793 
00794    return res;
00795 }

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

Definition at line 1580 of file res_calendar.c.

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), ast_strlen_zero(), ast_calendar_event::busy_state, calendar_join_attendees(), ast_calendar_event::categories, ast_datastore::data, ast_calendar_event::description, ast_calendar_event::end, event_notification_datastore, ast_calendar_event::location, LOG_WARNING, ast_calendar::name, ast_channel::name, ast_calendar_event::organizer, ast_calendar_event::owner, ast_calendar_event::priority, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.

01581 {
01582    struct ast_datastore *datastore;
01583    struct ast_calendar_event *event;
01584 
01585    if (ast_strlen_zero(data)) {
01586       ast_log(LOG_WARNING, "%s requires an argument\n", cmd);
01587       return -1;
01588    }
01589 
01590    ast_channel_lock(chan);
01591    if (!(datastore = ast_channel_datastore_find(chan, &event_notification_datastore, NULL))) {
01592       ast_log(LOG_WARNING, "There is no event notification datastore on '%s'!\n", chan->name);
01593       ast_channel_unlock(chan);
01594       return -1;
01595    }
01596    ast_channel_unlock(chan);
01597 
01598    if (!(event = datastore->data)) {
01599       ast_log(LOG_WARNING, "The datastore contains no data!\n");
01600       return -1;
01601    }
01602 
01603    if (!strcasecmp(data, "summary")) {
01604       ast_copy_string(buf, event->summary, len);
01605    } else if (!strcasecmp(data, "description")) {
01606       ast_copy_string(buf, event->description, len);
01607    } else if (!strcasecmp(data, "organizer")) {
01608       ast_copy_string(buf, event->organizer, len);
01609    } else if (!strcasecmp(data, "location")) {
01610       ast_copy_string(buf, event->location, len);
01611    } else if (!strcasecmp(data, "categories")) {
01612       ast_copy_string(buf, event->categories, len);
01613    } else if (!strcasecmp(data, "priority")) {
01614       snprintf(buf, len, "%d", event->priority);
01615    } else if (!strcasecmp(data, "calendar")) {
01616       ast_copy_string(buf, event->owner->name, len);
01617    } else if (!strcasecmp(data, "uid")) {
01618       ast_copy_string(buf, event->uid, len);
01619    } else if (!strcasecmp(data, "start")) {
01620       snprintf(buf, len, "%ld", (long)event->start);
01621    } else if (!strcasecmp(data, "end")) {
01622       snprintf(buf, len, "%ld", (long)event->end);
01623    } else if (!strcasecmp(data, "busystate")) {
01624       snprintf(buf, len, "%d", event->busy_state);
01625    } else if (!strcasecmp(data, "attendees")) {
01626       calendar_join_attendees(event, buf, len);
01627    }
01628 
01629 
01630    return 0;
01631 }

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

Definition at line 260 of file res_calendar.c.

References ast_str_case_hash(), and ast_calendar::name.

Referenced by load_module().

00261 {
00262    const struct ast_calendar *cal = obj;
00263    return ast_str_case_hash(cal->name);
00264 }

static int calendar_is_busy ( struct ast_calendar cal  )  [static]

Definition at line 350 of file res_calendar.c.

References ao2_callback, calendar_busy_callback(), ast_calendar::events, and OBJ_NODATA.

Referenced by calendar_busy_exec(), calendar_devstate_change(), calendarstate(), destroy_event(), and handle_show_calendars().

00351 {
00352    int is_busy = 0;
00353 
00354    ao2_callback(cal->events, OBJ_NODATA, calendar_busy_callback, &is_busy);
00355 
00356    return is_busy;
00357 }

static void calendar_join_attendees ( struct ast_calendar_event event,
char *  buf,
size_t  len 
) [static]

Definition at line 1209 of file res_calendar.c.

References ast_copy_string(), ast_free, AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_calendar_event::attendees, ast_calendar_attendee::data, LOG_ERROR, and ast_calendar_attendee::next.

Referenced by calendar_event_read(), and calendar_query_result_exec().

01210 {
01211    struct ast_str *tmp;
01212    struct ast_calendar_attendee *attendee;
01213 
01214    if (!(tmp = ast_str_create(32))) {
01215       ast_log(LOG_ERROR, "Could not allocate memory for attendees!\n");
01216       return;
01217    }
01218 
01219    AST_LIST_TRAVERSE(&event->attendees, attendee, next) {
01220       ast_str_append(&tmp, 0, "%s%s", attendee == AST_LIST_FIRST(&event->attendees) ? "" : ",", attendee->data);
01221    }
01222 
01223    ast_copy_string(buf, ast_str_buffer(tmp), len);
01224    ast_free(tmp);
01225 }

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

Definition at line 1118 of file res_calendar.c.

References add_event_to_list(), ao2_alloc, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, args, AST_APP_ARG, ast_calendar_unref_event(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_debug, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_calendar_event::end, eventlist_datastore_info, eventlist_destructor(), ast_calendar::events, events, find_calendar(), generate_random_string(), ast_datastore::inheritance, LOG_ERROR, LOG_WARNING, ast_calendar_event::start, ast_calendar_event::summary, and unref_calendar().

01119 {
01120    struct ast_calendar *cal;
01121    struct ao2_iterator i;
01122    struct ast_calendar_event *event;
01123    struct eventlist *events;
01124    time_t start = INT_MIN, end = INT_MAX;
01125    struct ast_datastore *eventlist_datastore;
01126    AST_DECLARE_APP_ARGS(args,
01127       AST_APP_ARG(calendar);
01128       AST_APP_ARG(start);
01129       AST_APP_ARG(end);
01130    );
01131 
01132    if (!chan) {
01133       ast_log(LOG_WARNING, "%s requires a channel to store the data on\n", cmd);
01134       return -1;
01135    }
01136 
01137    AST_STANDARD_APP_ARGS(args, data);
01138 
01139    if (ast_strlen_zero(args.calendar)) {
01140       ast_log(LOG_WARNING, "%s requires a calendar argument\n", cmd);
01141       return -1;
01142    }
01143 
01144    if (!(cal = find_calendar(args.calendar))) {
01145       ast_log(LOG_WARNING, "Unknown calendar '%s'\n", args.calendar);
01146       return -1;
01147    }
01148 
01149    if (!(events = ao2_alloc(sizeof(*events), eventlist_destructor))) {
01150       ast_log(LOG_ERROR, "Unable to allocate memory for event list\n");
01151       cal = unref_calendar(cal);
01152       return -1;
01153    }
01154 
01155    if (!ast_strlen_zero(args.start)) {
01156       start = atoi(args.start);
01157    }
01158 
01159    if (!ast_strlen_zero(args.end)) {
01160       end = atoi(args.end);
01161    }
01162 
01163    i = ao2_iterator_init(cal->events, 0);
01164    while ((event = ao2_iterator_next(&i))) {
01165       if (!(start > event->end || end < event->start)) {
01166          ast_debug(10, "%s (%ld - %ld) overlapped with (%ld - %ld)\n", event->summary, (long) event->start, (long) event->end, (long) start, (long) end);
01167          if (add_event_to_list(events, event, start, end) < 0) {
01168             event = ast_calendar_unref_event(event);
01169             cal = unref_calendar(cal);
01170             ao2_ref(events, -1);
01171             ao2_iterator_destroy(&i);
01172             return -1;
01173          }
01174       }
01175 
01176       event = ast_calendar_unref_event(event);
01177    }
01178    ao2_iterator_destroy(&i);
01179 
01180    ast_channel_lock(chan);
01181    do {
01182       generate_random_string(buf, len);
01183    } while (ast_channel_datastore_find(chan, &eventlist_datastore_info, buf));
01184    ast_channel_unlock(chan);
01185 
01186    if (!(eventlist_datastore = ast_datastore_alloc(&eventlist_datastore_info, buf))) {
01187       ast_log(LOG_ERROR, "Could not allocate datastore!\n");
01188       cal = unref_calendar(cal);
01189       ao2_ref(events, -1);
01190       return -1;
01191    }
01192 
01193    eventlist_datastore->inheritance = DATASTORE_INHERIT_FOREVER;
01194    eventlist_datastore->data = events;
01195 
01196    ast_channel_lock(chan);
01197    ast_channel_datastore_add(chan, eventlist_datastore);
01198    ast_channel_unlock(chan);
01199 
01200    cal = unref_calendar(cal);
01201    return 0;
01202 }

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

Definition at line 1227 of file res_calendar.c.

References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_calendar_event::busy_state, calendar_join_attendees(), ast_calendar_event::categories, ast_datastore::data, ast_calendar_event::description, ast_calendar_event::end, evententry::event, eventlist_datastore_info, events, evententry::list, ast_calendar_event::location, LOG_WARNING, ast_calendar::name, ast_channel::name, ast_calendar_event::organizer, ast_calendar_event::owner, ast_calendar_event::priority, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.

01228 {
01229    struct ast_datastore *datastore;
01230    struct eventlist *events;
01231    struct evententry *entry;
01232    int row = 1;
01233    size_t listlen = 0;
01234    AST_DECLARE_APP_ARGS(args,
01235       AST_APP_ARG(id);
01236       AST_APP_ARG(field);
01237       AST_APP_ARG(row);
01238    );
01239 
01240    if (!chan) {
01241       ast_log(LOG_WARNING, "%s requires a channel\n", cmd);
01242       return -1;
01243    }
01244 
01245    AST_STANDARD_APP_ARGS(args, data);
01246 
01247    if (ast_strlen_zero(args.id) || ast_strlen_zero(args.field)) {
01248       ast_log(LOG_WARNING, "%s requires an id and a field", cmd);
01249       return -1;
01250    }
01251 
01252    ast_channel_lock(chan);
01253    if (!(datastore = ast_channel_datastore_find(chan, &eventlist_datastore_info, args.id))) {
01254       ast_log(LOG_WARNING, "There is no event notification datastore with id '%s' on '%s'!\n", args.id, chan->name);
01255       ast_channel_unlock(chan);
01256       return -1;
01257    }
01258    ast_channel_unlock(chan);
01259 
01260    if (!(events = datastore->data)) {
01261       ast_log(LOG_WARNING, "The datastore contains no data!\n");
01262       return -1;
01263    }
01264 
01265    if (!ast_strlen_zero(args.row)) {
01266       row = atoi(args.row);
01267    }
01268 
01269    AST_LIST_TRAVERSE(events, entry, list) {
01270       listlen++;
01271    }
01272 
01273    if (!strcasecmp(args.field, "getnum")) {
01274       snprintf(buf, len, "%zu", listlen);
01275       return 0;
01276    }
01277 
01278    AST_LIST_TRAVERSE(events, entry, list) {
01279       if (--row) {
01280          continue;
01281       }
01282       if (!strcasecmp(args.field, "summary")) {
01283          ast_copy_string(buf, entry->event->summary, len);
01284       } else if (!strcasecmp(args.field, "description")) {
01285          ast_copy_string(buf, entry->event->description, len);
01286       } else if (!strcasecmp(args.field, "organizer")) {
01287          ast_copy_string(buf, entry->event->organizer, len);
01288       } else if (!strcasecmp(args.field, "location")) {
01289          ast_copy_string(buf, entry->event->location, len);
01290       } else if (!strcasecmp(args.field, "categories")) {
01291          ast_copy_string(buf, entry->event->categories, len);
01292       } else if (!strcasecmp(args.field, "priority")) {
01293          snprintf(buf, len, "%d", entry->event->priority);
01294       } else if (!strcasecmp(args.field, "calendar")) {
01295          ast_copy_string(buf, entry->event->owner->name, len);
01296       } else if (!strcasecmp(args.field, "uid")) {
01297          ast_copy_string(buf, entry->event->uid, len);
01298       } else if (!strcasecmp(args.field, "start")) {
01299          snprintf(buf, len, "%ld", (long) entry->event->start);
01300       } else if (!strcasecmp(args.field, "end")) {
01301          snprintf(buf, len, "%ld", (long) entry->event->end);
01302       } else if (!strcasecmp(args.field, "busystate")) {
01303          snprintf(buf, len, "%d", entry->event->busy_state);
01304       } else if (!strcasecmp(args.field, "attendees")) {
01305          calendar_join_attendees(entry->event, buf, len);
01306       } else {
01307          ast_log(LOG_WARNING, "Unknown field '%s'\n", args.field);
01308       }
01309       break;
01310    }
01311 
01312    return 0;
01313 }

static int calendar_write_exec ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

Definition at line 1320 of file res_calendar.c.

References AST_APP_ARG, ast_calendar_event_alloc(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_tvnow(), find_calendar(), LOG_ERROR, LOG_WARNING, ast_calendar::name, ast_calendar_event::owner, ast_calendar::tech, and ast_calendar_tech::write_event.

01321 {
01322    int i, j, ret = -1;
01323    char *val_dup = NULL;
01324    struct ast_calendar *cal = NULL;
01325    struct ast_calendar_event *event = NULL;
01326    struct timeval tv = ast_tvnow();
01327    AST_DECLARE_APP_ARGS(fields,
01328       AST_APP_ARG(field)[10];
01329    );
01330    AST_DECLARE_APP_ARGS(values,
01331       AST_APP_ARG(value)[10];
01332    );
01333 
01334    if (!(val_dup = ast_strdup(value))) {
01335       ast_log(LOG_ERROR, "Could not allocate memory for values\n");
01336       return -1;
01337    }
01338 
01339    AST_STANDARD_APP_ARGS(fields, data);
01340    AST_STANDARD_APP_ARGS(values, val_dup);
01341 
01342    /* XXX Eventually we will support unnamed calendars, so if we don't find one, we parse
01343     * for a calendar type and create it */
01344    if (!(cal = find_calendar(fields.field[0]))) {
01345       ast_log(LOG_WARNING, "Couldn't find calendar '%s'\n", fields.field[0]);
01346       goto write_cleanup;
01347    }
01348 
01349    if (!(cal->tech->write_event)) {
01350       ast_log(LOG_WARNING, "Calendar '%s' has no write function!\n", cal->name);
01351       goto write_cleanup;
01352    }
01353 
01354    if (!(event = ast_calendar_event_alloc(cal))) {
01355       goto write_cleanup;
01356    }
01357 
01358    if (ast_strlen_zero(fields.field[0])) {
01359       ast_log(LOG_WARNING, "CALENDAR_WRITE requires a calendar name!\n");
01360       goto write_cleanup;
01361    }
01362 
01363    if (fields.argc - 1 != values.argc) {
01364       ast_log(LOG_WARNING, "CALENDAR_WRITE should have the same number of fields (%d) and values (%d)!\n", fields.argc - 1, values.argc);
01365       goto write_cleanup;
01366    }
01367 
01368    event->owner = cal;
01369 
01370    for (i = 1, j = 0; i < fields.argc; i++, j++) {
01371       if (!strcasecmp(fields.field[i], "summary")) {
01372          ast_string_field_set(event, summary, values.value[j]);
01373       } else if (!strcasecmp(fields.field[i], "description")) {
01374          ast_string_field_set(event, description, values.value[j]);
01375       } else if (!strcasecmp(fields.field[i], "organizer")) {
01376          ast_string_field_set(event, organizer, values.value[j]);
01377       } else if (!strcasecmp(fields.field[i], "location")) {
01378          ast_string_field_set(event, location, values.value[j]);
01379       } else if (!strcasecmp(fields.field[i], "categories")) {
01380          ast_string_field_set(event, categories, values.value[j]);
01381       } else if (!strcasecmp(fields.field[i], "priority")) {
01382          event->priority = atoi(values.value[j]);
01383       } else if (!strcasecmp(fields.field[i], "uid")) {
01384          ast_string_field_set(event, uid, values.value[j]);
01385       } else if (!strcasecmp(fields.field[i], "start")) {
01386          event->start = atoi(values.value[j]);
01387       } else if (!strcasecmp(fields.field[i], "end")) {
01388          event->end = atoi(values.value[j]);
01389       } else if (!strcasecmp(fields.field[i], "busystate")) {
01390          event->busy_state = atoi(values.value[j]);
01391       } else {
01392          ast_log(LOG_WARNING, "Unknown calendar event field '%s'\n", fields.field[i]);
01393       }
01394    }
01395 
01396    if (!event->start) {
01397       event->start = tv.tv_sec;
01398    }
01399 
01400    if (!event->end) {
01401       event->end = tv.tv_sec;
01402    }
01403 
01404    if((ret = cal->tech->write_event(event))) {
01405       ast_log(LOG_WARNING, "Writing event to calendar '%s' failed!\n", cal->name);
01406    }
01407 
01408 write_cleanup:
01409    if (cal) {
01410       cal = unref_calendar(cal);
01411    }
01412    if (event) {
01413       event = ast_calendar_unref_event(event);
01414    }
01415    if (val_dup) {
01416       ast_free(val_dup);
01417    }
01418 
01419    return ret;
01420 }

static enum ast_device_state calendarstate ( const char *  data  )  [static]

Definition at line 359 of file res_calendar.c.

References AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, ast_device_state(), ast_strlen_zero(), calendar_is_busy(), find_calendar(), ast_calendar_tech::is_busy, ast_calendar::tech, and unref_calendar().

Referenced by load_module().

00360 {
00361    enum ast_device_state state;
00362    struct ast_calendar *cal;
00363 
00364    if (ast_strlen_zero(data) || (!(cal = find_calendar(data)))) {
00365       return AST_DEVICE_INVALID;
00366    }
00367 
00368    if (cal->tech->is_busy) {
00369       state = cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE;
00370    } else {
00371       state = calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE;
00372    }
00373 
00374    cal = unref_calendar(cal);
00375    return state;
00376 }

static int cb_pending_deletion ( void *  user_data,
void *  arg,
int  flags 
) [static]

Definition at line 1638 of file res_calendar.c.

References CMP_MATCH, and ast_calendar::pending_deletion.

Referenced by reload().

01639 {
01640    struct ast_calendar *cal = user_data;
01641 
01642    cal->pending_deletion = 1;
01643 
01644    return CMP_MATCH;
01645 }

static int cb_rm_pending_deletion ( void *  user_data,
void *  arg,
int  flags 
) [static]

Definition at line 1647 of file res_calendar.c.

References CMP_MATCH, and ast_calendar::pending_deletion.

Referenced by reload().

01648 {
01649    struct ast_calendar *cal = user_data;
01650 
01651    return cal->pending_deletion ? CMP_MATCH : 0;
01652 }

static int clear_events_cb ( void *  user_data,
void *  arg,
int  flags 
) [static]

Definition at line 587 of file res_calendar.c.

References CMP_MATCH, and destroy_event().

Referenced by ast_calendar_clear_events().

00588 {
00589    struct ast_calendar_event *event = user_data;
00590 
00591    event = destroy_event(event);
00592 
00593    return CMP_MATCH;
00594 }

static void copy_event_data ( struct ast_calendar_event dst,
struct ast_calendar_event src 
) [static]

Definition at line 831 of file res_calendar.c.

References ast_calendar_event::alarm, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_string_field_set, ast_calendar_event::attendees, ast_calendar_event::busy_state, ast_calendar_event::categories, ast_calendar_event::description, ast_calendar_event::end, ast_calendar_event::location, ast_calendar_attendee::next, ast_calendar_event::organizer, ast_calendar_event::owner, ast_calendar_event::priority, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.

Referenced by merge_events_cb().

00832 {
00833    struct ast_calendar_attendee *attendee;
00834 
00835    ast_string_field_set(dst, summary, src->summary);
00836    ast_string_field_set(dst, description, src->description);
00837    ast_string_field_set(dst, organizer, src->organizer);
00838    ast_string_field_set(dst, location, src->location);
00839    ast_string_field_set(dst, uid, src->uid);
00840    ast_string_field_set(dst, categories, src->categories);
00841    dst->priority = src->priority;
00842    dst->owner = src->owner;
00843    dst->start = src->start;
00844    dst->end = src->end;
00845    dst->alarm = src->alarm;
00846    dst->busy_state = src->busy_state;
00847 
00848    /* Delete any existing attendees */
00849    while ((attendee = AST_LIST_REMOVE_HEAD(&dst->attendees, next))) {
00850       ast_free(attendee);
00851    }
00852 
00853    /* Copy over the new attendees */
00854    while ((attendee = AST_LIST_REMOVE_HEAD(&src->attendees, next))) {
00855       AST_LIST_INSERT_TAIL(&dst->attendees, attendee, next);
00856    }
00857 }

static struct ast_calendar_event* destroy_event ( struct ast_calendar_event event  )  [static]

Definition at line 562 of file res_calendar.c.

References ast_debug, AST_DEVICE_BUSY, AST_DEVICE_NOT_INUSE, ast_devstate_changed(), ast_sched_del(), ast_calendar_event::bs_end_sched, ast_calendar_event::bs_start_sched, calendar_is_busy(), ast_calendar::name, ast_calendar_event::notify_sched, ast_calendar_event::owner, and sched.

Referenced by clear_events_cb(), and merge_events_cb().

00563 {
00564    if (event->notify_sched > -1 && ast_sched_del(sched, event->notify_sched)) {
00565       ast_debug(3, "Notification running, can't delete sched entry\n");
00566    }
00567    if (event->bs_start_sched > -1 && ast_sched_del(sched, event->bs_start_sched)) {
00568       ast_debug(3, "Devicestate update (start) running, can't delete sched entry\n");
00569    }
00570    if (event->bs_end_sched > -1 && ast_sched_del(sched, event->bs_end_sched)) {
00571       ast_debug(3, "Devicestate update (end) running, can't delete sched entry\n");
00572    }
00573 
00574    /* If an event is being deleted and we've fired an event changing the status at the beginning,
00575     * but haven't hit the end event yet, go ahead and set the devicestate to the current busy status */
00576    if (event->bs_start_sched < 0 && event->bs_end_sched >= 0) {
00577       if (!calendar_is_busy(event->owner)) {
00578          ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name);
00579       } else {
00580          ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name);
00581       }
00582    }
00583 
00584    return NULL;
00585 }

static void* do_notify ( void *  data  )  [static]

Definition at line 676 of file res_calendar.c.

References ao2_ref, ast_calendar_unref_event(), ast_channel_alloc, ast_channel_datastore_add(), ast_channel_release(), ast_copy_string(), ast_datastore_alloc, ast_dial_answered_steal(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), AST_DIAL_OPTION_ANSWER_EXEC, ast_dial_option_global_enable(), AST_DIAL_RESULT_ANSWERED, ast_dial_run(), ast_dial_set_global_timeout(), AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_pbx_run(), AST_STATE_DOWN, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_verb, ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, event_notification_datastore, ast_channel::exten, generate_random_string(), ast_datastore::inheritance, LOG_ERROR, LOG_WARNING, ast_calendar::name, ast_channel::nativeformats, ast_calendar::notify_app, ast_calendar::notify_appdata, ast_calendar::notify_channel, ast_calendar::notify_context, ast_calendar::notify_extension, ast_calendar::notify_waittime, null_tech, ast_calendar_event::owner, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::tech, and ast_channel::writeformat.

Referenced by calendar_event_notify().

00677 {
00678    struct ast_calendar_event *event = data;
00679    struct ast_dial *dial = NULL;
00680    struct ast_str *apptext = NULL;
00681    struct ast_datastore *datastore;
00682    enum ast_dial_result res;
00683    struct ast_channel *chan = NULL;
00684    char *tech, *dest;
00685    char buf[8];
00686 
00687    tech = ast_strdupa(event->owner->notify_channel);
00688 
00689    if ((dest = strchr(tech, '/'))) {
00690       *dest = '\0';
00691       dest++;
00692    } else {
00693       ast_log(LOG_WARNING, "Channel should be in form Tech/Dest (was '%s')\n", tech);
00694       goto notify_cleanup;
00695    }
00696 
00697    if (!(dial = ast_dial_create())) {
00698       ast_log(LOG_ERROR, "Could not create dial structure\n");
00699       goto notify_cleanup;
00700    }
00701 
00702    if (ast_dial_append(dial, tech, dest) < 0) {
00703       ast_log(LOG_ERROR, "Could not append channel\n");
00704       goto notify_cleanup;
00705    }
00706 
00707    ast_dial_set_global_timeout(dial, event->owner->notify_waittime);
00708    generate_random_string(buf, sizeof(buf));
00709 
00710    if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, 0, 0, 0, 0, 0, 0, 0, "Calendar/%s-%s", event->owner->name, buf))) {
00711       ast_log(LOG_ERROR, "Could not allocate notification channel\n");
00712       goto notify_cleanup;
00713    }
00714 
00715    chan->tech = &null_tech;
00716    chan->nativeformats = chan->writeformat = chan->rawwriteformat =
00717       chan->readformat = chan->rawreadformat = AST_FORMAT_SLINEAR;
00718 
00719    if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) {
00720       ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n");
00721       goto notify_cleanup;
00722    }
00723 
00724    datastore->data = event;
00725    datastore->inheritance = DATASTORE_INHERIT_FOREVER;
00726 
00727    ao2_ref(event, +1);
00728    res = ast_channel_datastore_add(chan, datastore);
00729 
00730    if (!(apptext = ast_str_create(32))) {
00731       goto notify_cleanup;
00732    }
00733 
00734    if (!ast_strlen_zero(event->owner->notify_app)) {
00735       ast_str_set(&apptext, 0, "%s,%s", event->owner->notify_app, event->owner->notify_appdata);
00736       ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, ast_str_buffer(apptext));
00737    } else {
00738    }
00739 
00740    ast_verb(3, "Dialing %s for notification on calendar %s\n", event->owner->notify_channel, event->owner->name);
00741    res = ast_dial_run(dial, chan, 0);
00742 
00743    if (res != AST_DIAL_RESULT_ANSWERED) {
00744       ast_verb(3, "Notification call for %s was not completed\n", event->owner->name);
00745    } else {
00746       struct ast_channel *answered;
00747 
00748       answered = ast_dial_answered_steal(dial);
00749       if (ast_strlen_zero(event->owner->notify_app)) {
00750          ast_copy_string(answered->context, event->owner->notify_context, sizeof(answered->context));
00751          ast_copy_string(answered->exten, event->owner->notify_extension, sizeof(answered->exten));
00752          answered->priority = 1;
00753          ast_pbx_run(answered);
00754       }
00755    }
00756 
00757 notify_cleanup:
00758    if (apptext) {
00759       ast_free(apptext);
00760    }
00761    if (dial) {
00762       ast_dial_destroy(dial);
00763    }
00764    if (chan) {
00765       ast_channel_release(chan);
00766    }
00767 
00768    event = ast_calendar_unref_event(event);
00769 
00770    return NULL;
00771 }

static void* do_refresh ( void *  data  )  [static]

Definition at line 1680 of file res_calendar.c.

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_tvnow(), refreshlock, and sched.

01681 {
01682    for (;;) {
01683       struct timeval now = ast_tvnow();
01684       struct timespec ts = {0,};
01685       int wait;
01686 
01687       ast_mutex_lock(&refreshlock);
01688 
01689       while (!module_unloading) {
01690          if ((wait = ast_sched_wait(sched)) < 0) {
01691             wait = 1000;
01692          }
01693 
01694          ts.tv_sec = (now.tv_sec + wait / 1000) + 1;
01695          if (ast_cond_timedwait(&refresh_condition, &refreshlock, &ts) == ETIMEDOUT) {
01696             break;
01697          }
01698       }
01699       ast_mutex_unlock(&refreshlock);
01700 
01701       if (module_unloading) {
01702          break;
01703       }
01704       ast_sched_runq(sched);
01705    }
01706 
01707    return NULL;
01708 }

static char* epoch_to_string ( char *  buf,
size_t  buflen,
time_t  epoch 
) [static]

Definition at line 1458 of file res_calendar.c.

References ast_localtime(), and ast_strftime().

Referenced by handle_show_calendar().

01459 {
01460    struct ast_tm tm;
01461    struct timeval tv = {
01462       .tv_sec = epoch,
01463    };
01464 
01465    if (!epoch) {
01466       *buf = '\0';
01467       return buf;
01468    }
01469    ast_localtime(&tv, &tm, NULL);
01470    ast_strftime(buf, buflen, "%F %r %z", &tm);
01471 
01472    return buf;
01473 }

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

Definition at line 286 of file res_calendar.c.

References CMP_MATCH, CMP_STOP, and ast_calendar_event::uid.

Referenced by ast_calendar_event_container_alloc(), and build_calendar().

00287 {
00288    const struct ast_calendar_event *one = obj, *two = arg;
00289    return !strcmp(one->uid, two->uid) ? CMP_MATCH | CMP_STOP : 0;
00290 }

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

Definition at line 280 of file res_calendar.c.

References ast_str_hash(), evententry::event, and ast_calendar_event::uid.

Referenced by ast_calendar_event_container_alloc(), and build_calendar().

00281 {
00282    const struct ast_calendar_event *event = obj;
00283    return ast_str_hash(event->uid);
00284 }

static void event_notification_destroy ( void *  data  )  [static]

Definition at line 630 of file res_calendar.c.

References ast_calendar_unref_event().

00631 {
00632    struct ast_calendar_event *event = data;
00633 
00634    event = ast_calendar_unref_event(event);
00635 
00636 }

static void * event_notification_duplicate ( void *  data  )  [static]

Definition at line 638 of file res_calendar.c.

References ao2_ref.

00639 {
00640    struct ast_calendar_event *event = data;
00641 
00642    if (!event) {
00643       return NULL;
00644    }
00645 
00646    ao2_ref(event, +1);
00647 
00648    return event;
00649 }

static void eventlist_destroy ( void *  data  )  [static]

Definition at line 1098 of file res_calendar.c.

References ao2_ref, and events.

01099 {
01100    struct eventlist *events = data;
01101 
01102    ao2_ref(events, -1);
01103 }

static void eventlist_destructor ( void *  obj  )  [static]

Definition at line 325 of file res_calendar.c.

References ao2_ref, ast_free, AST_LIST_REMOVE_HEAD, evententry::event, events, and evententry::list.

Referenced by calendar_query_exec().

00326 {
00327    struct eventlist *events = obj;
00328    struct evententry *entry;
00329 
00330    while ((entry = AST_LIST_REMOVE_HEAD(events, list))) {
00331       ao2_ref(entry->event, -1);
00332       ast_free(entry);
00333    }
00334 }

static void * eventlist_duplicate ( void *  data  )  [static]

Definition at line 1105 of file res_calendar.c.

References ao2_ref, and events.

01106 {
01107    struct eventlist *events = data;
01108 
01109    if (!events) {
01110       return NULL;
01111    }
01112 
01113    ao2_ref(events, +1);
01114 
01115    return events;
01116 }

static struct ast_calendar* find_calendar ( const char *  name  )  [static]

Definition at line 272 of file res_calendar.c.

References ao2_find, calendars, ast_calendar::name, and OBJ_POINTER.

Referenced by build_calendar(), calendar_busy_exec(), calendar_query_exec(), calendar_write_exec(), calendarstate(), and handle_show_calendar().

00273 {
00274    struct ast_calendar tmp = {
00275       .name = name,
00276    };
00277    return ao2_find(calendars, &tmp, OBJ_POINTER);
00278 }

static struct ast_calendar_event* find_event ( struct ao2_container events,
const char *  uid 
) [static]

Definition at line 292 of file res_calendar.c.

References ao2_find, events, OBJ_POINTER, and ast_calendar_event::uid.

Referenced by merge_events_cb().

00293 {
00294    struct ast_calendar_event tmp = {
00295       .uid = uid,
00296    };
00297    return ao2_find(events, &tmp, OBJ_POINTER);
00298 }

static char* generate_random_string ( char *  buf,
size_t  size 
) [static]

Generate 32 byte random string (stolen from chan_sip.c).

Definition at line 652 of file res_calendar.c.

References ast_random().

00653 {
00654    long val[4];
00655    int x;
00656 
00657    for (x = 0; x < 4; x++) {
00658       val[x] = ast_random();
00659    }
00660    snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]);
00661 
00662    return buf;
00663 }

static char* handle_dump_sched ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1555 of file res_calendar.c.

References ast_sched_dump(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, sched, and ast_cli_entry::usage.

01556 {
01557    switch(cmd) {
01558    case CLI_INIT:
01559       e->command = "calendar dump sched";
01560       e->usage =
01561          "Usage: calendar dump sched\n"
01562          "       Dump the calendar sched context";
01563       return NULL;
01564 
01565    case CLI_GENERATE:
01566       return NULL;
01567    }
01568 
01569    ast_sched_dump(sched);
01570 
01571    return CLI_SUCCESS;
01572 }

static char* handle_show_calendar ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1475 of file res_calendar.c.

References ast_calendar_event::alarm, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli_args::argc, ast_cli_args::argv, ast_calendar_unref_event(), ast_cli(), ast_strdup, ast_calendar::autoreminder, ast_calendar_event::categories, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_calendar_event::description, ast_calendar_event::end, epoch_to_string(), ast_calendar::events, ast_cli_args::fd, find_calendar(), FORMAT, FORMAT2, ast_calendar_event::location, ast_cli_args::n, ast_calendar::name, ast_calendar::notify_app, ast_calendar::notify_appdata, ast_calendar::notify_channel, ast_calendar::notify_context, ast_calendar::notify_extension, ast_calendar_event::organizer, ast_cli_args::pos, ast_calendar_event::priority, ast_calendar::refresh, ast_calendar_event::start, ast_calendar_event::summary, ast_calendar::timeframe, ast_calendar_event::uid, unref_calendar(), ast_cli_entry::usage, and ast_cli_args::word.

01476 {
01477 #define FORMAT "%-17.17s : %-20.20s\n"
01478 #define FORMAT2 "%-12.12s: %-40.60s\n"
01479    struct ao2_iterator i;
01480    struct ast_calendar *cal;
01481    struct ast_calendar_event *event;
01482    int which = 0;
01483    char *ret = NULL;
01484 
01485    switch(cmd) {
01486    case CLI_INIT:
01487       e->command = "calendar show calendar";
01488       e->usage =
01489          "Usage: calendar show calendar <calendar name>\n"
01490          "       Displays information about a calendar\n";
01491       return NULL;
01492 
01493    case CLI_GENERATE:
01494       if (a->pos != 3) {
01495          return NULL;
01496       }
01497       i = ao2_iterator_init(calendars, 0);
01498       while ((cal = ao2_iterator_next(&i))) {
01499          if (!strncasecmp(a->word, cal->name, strlen(a->word)) && ++which > a->n) {
01500             ret = ast_strdup(cal->name);
01501             cal = unref_calendar(cal);
01502             break;
01503          }
01504          cal = unref_calendar(cal);
01505       }
01506       ao2_iterator_destroy(&i);
01507       return ret;
01508    }
01509 
01510    if (a->argc != 4) {
01511       return CLI_SHOWUSAGE;
01512    }
01513 
01514    if (!(cal = find_calendar(a->argv[3]))) {
01515       return NULL;
01516    }
01517 
01518    ast_cli(a->fd, FORMAT, "Name", cal->name);
01519    ast_cli(a->fd, FORMAT, "Notify channel", cal->notify_channel);
01520    ast_cli(a->fd, FORMAT, "Notify context", cal->notify_context);
01521    ast_cli(a->fd, FORMAT, "Notify extension", cal->notify_extension);
01522    ast_cli(a->fd, FORMAT, "Notify application", cal->notify_app);
01523    ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata);
01524    ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh);
01525    ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe);
01526    ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder);
01527    ast_cli(a->fd, "%s\n", "Events");
01528    ast_cli(a->fd, "%s\n", "------");
01529 
01530    i = ao2_iterator_init(cal->events, 0);
01531    while ((event = ao2_iterator_next(&i))) {
01532       char buf[100];
01533 
01534       ast_cli(a->fd, FORMAT2, "Summary", event->summary);
01535       ast_cli(a->fd, FORMAT2, "Description", event->description);
01536       ast_cli(a->fd, FORMAT2, "Organizer", event->organizer);
01537       ast_cli(a->fd, FORMAT2, "Location", event->location);
01538       ast_cli(a->fd, FORMAT2, "Categories", event->categories);
01539       ast_cli(a->fd, "%-12.12s: %d\n", "Priority", event->priority);
01540       ast_cli(a->fd, FORMAT2, "UID", event->uid);
01541       ast_cli(a->fd, FORMAT2, "Start", epoch_to_string(buf, sizeof(buf), event->start));
01542       ast_cli(a->fd, FORMAT2, "End", epoch_to_string(buf, sizeof(buf), event->end));
01543       ast_cli(a->fd, FORMAT2, "Alarm", epoch_to_string(buf, sizeof(buf), event->alarm));
01544       ast_cli(a->fd, "\n");
01545 
01546       event = ast_calendar_unref_event(event);
01547    }
01548    ao2_iterator_destroy(&i);
01549    cal = unref_calendar(cal);
01550    return CLI_SUCCESS;
01551 #undef FORMAT
01552 #undef FORMAT2
01553 }

static char* handle_show_calendars ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command to list available calendars.

Definition at line 1428 of file res_calendar.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli(), calendar_is_busy(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, ast_calendar::name, ast_calendar::tech, ast_calendar_tech::type, unref_calendar(), and ast_cli_entry::usage.

01429 {
01430 #define FORMAT "%-20.20s %-10.10s %-6.6s\n"
01431    struct ao2_iterator i;
01432    struct ast_calendar *cal;
01433 
01434    switch(cmd) {
01435    case CLI_INIT:
01436       e->command = "calendar show calendars";
01437       e->usage =
01438          "Usage: calendar show calendars\n"
01439          "       Lists all registered calendars.\n";
01440       return NULL;
01441    case CLI_GENERATE:
01442       return NULL;
01443    }
01444 
01445    ast_cli(a->fd, FORMAT, "Calendar", "Type", "Status");
01446    ast_cli(a->fd, FORMAT, "--------", "----", "------");
01447    i = ao2_iterator_init(calendars, 0);
01448    while ((cal = ao2_iterator_next(&i))) {
01449       ast_cli(a->fd, FORMAT, cal->name, cal->tech->type, calendar_is_busy(cal) ? "busy" : "free");
01450       cal = unref_calendar(cal);
01451    }
01452    ao2_iterator_destroy(&i);
01453 
01454    return CLI_SUCCESS;
01455 #undef FORMAT
01456 }

static int load_config ( int  reload  )  [static]

Definition at line 970 of file res_calendar.c.

References ast_config_destroy(), ast_config_load2(), ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, calendar_config, CONFIG_FLAG_FILEUNCHANGED, config_lock, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, and LOG_ERROR.

00971 {
00972    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00973    struct ast_config *tmpcfg;
00974 
00975    if (!(tmpcfg = ast_config_load2("calendar.conf", "calendar", config_flags)) ||
00976       tmpcfg == CONFIG_STATUS_FILEINVALID) {
00977       ast_log(LOG_ERROR, "Unable to load config calendar.conf\n");
00978       return -1;
00979    }
00980 
00981    if (tmpcfg == CONFIG_STATUS_FILEUNCHANGED) {
00982       return 0;
00983    }
00984 
00985    ast_rwlock_wrlock(&config_lock);
00986    if (calendar_config) {
00987       ast_config_destroy(calendar_config);
00988    }
00989 
00990    calendar_config = tmpcfg;
00991    ast_rwlock_unlock(&config_lock);
00992 
00993    return 0;
00994 }

static int load_module ( void   )  [static]

Definition at line 1745 of file res_calendar.c.

References ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), ast_cond_init, ast_custom_function_register, ast_devstate_prov_add(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init, ast_pthread_create_background, CALENDAR_BUCKETS, calendar_busy_function, calendar_cli, calendar_cmp_fn(), calendar_event_function, calendar_hash_fn(), calendar_query_function, calendar_query_result_function, calendar_write_function, calendarstate(), do_refresh(), load_config(), LOG_ERROR, refreshlock, reloadlock, sched, and sched_context_create().

01746 {
01747    if (!(calendars = ao2_container_alloc(CALENDAR_BUCKETS, calendar_hash_fn, calendar_cmp_fn))) {
01748       ast_log(LOG_ERROR, "Unable to allocate calendars container!\n");
01749       return AST_MODULE_LOAD_FAILURE;
01750    }
01751 
01752    if (load_config(0)) {
01753       /* We don't have calendar support enabled */
01754       return AST_MODULE_LOAD_DECLINE;
01755    }
01756 
01757    ast_mutex_init(&refreshlock);
01758    ast_cond_init(&refresh_condition, NULL);
01759    ast_mutex_init(&reloadlock);
01760 
01761    if (!(sched = sched_context_create())) {
01762       ast_log(LOG_ERROR, "Unable to create sched context\n");
01763       return AST_MODULE_LOAD_FAILURE;
01764    }
01765 
01766    if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) {
01767       ast_log(LOG_ERROR, "Unable to start refresh thread--notifications disabled!\n");
01768    }
01769 
01770    ast_custom_function_register(&calendar_busy_function);
01771    ast_custom_function_register(&calendar_event_function);
01772    ast_custom_function_register(&calendar_query_function);
01773    ast_custom_function_register(&calendar_query_result_function);
01774    ast_custom_function_register(&calendar_write_function);
01775    ast_cli_register_multiple(calendar_cli, ARRAY_LEN(calendar_cli));
01776 
01777    ast_devstate_prov_add("Calendar", calendarstate);
01778 
01779    return AST_MODULE_LOAD_SUCCESS;
01780 }

static int load_tech_calendars ( struct ast_calendar_tech tech  )  [static]

Definition at line 454 of file res_calendar.c.

References ast_calendar_unregister(), ast_category_browse(), ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_variable_retrieve(), build_calendar(), calendar_config, config_lock, LOG_WARNING, ast_calendar::tech, ast_calendar_tech::type, and unref_calendar().

Referenced by ast_calendar_register(), and reload().

00455 {
00456    struct ast_calendar *cal;
00457    const char *cat = NULL;
00458    const char *val;
00459 
00460    if (!calendar_config) {
00461       ast_log(LOG_WARNING, "Calendar support disabled, not loading %s calendar module\n", tech->type);
00462       return -1;
00463    }
00464 
00465    ast_rwlock_wrlock(&config_lock);
00466    while ((cat = ast_category_browse(calendar_config, cat))) {
00467       if (!strcasecmp(cat, "general")) {
00468          continue;
00469       }
00470 
00471       if (!(val = ast_variable_retrieve(calendar_config, cat, "type")) || strcasecmp(val, tech->type)) {
00472          continue;
00473       }
00474 
00475       /* A serious error occurred loading calendars from this tech and it should be disabled */
00476       if (!(cal = build_calendar(calendar_config, cat, tech))) {
00477          ast_calendar_unregister(tech);
00478          ast_rwlock_unlock(&config_lock);
00479          return -1;
00480       }
00481 
00482       cal = unref_calendar(cal);
00483    }
00484 
00485    ast_rwlock_unlock(&config_lock);
00486 
00487    return 0;
00488 }

static int match_caltech_cb ( void *  user_data,
void *  arg,
int  flags 
) [static]

Definition at line 511 of file res_calendar.c.

References CMP_MATCH, and ast_calendar::tech.

Referenced by ast_calendar_unregister().

00512 {
00513    struct ast_calendar *cal = user_data;
00514    struct ast_calendar_tech *tech = arg;
00515 
00516    if (cal->tech == tech) {
00517       return CMP_MATCH;
00518    }
00519 
00520    return 0;
00521 }

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

Definition at line 921 of file res_calendar.c.

References ao2_unlink, ast_calendar_unref_event(), CMP_MATCH, copy_event_data(), destroy_event(), find_event(), ast_calendar_event::owner, schedule_calendar_event(), and ast_calendar_event::uid.

Referenced by ast_calendar_merge_events().

00922 {
00923    struct ast_calendar_event *old_event = obj, *new_event;
00924    struct ao2_container *new_events = arg;
00925 
00926    /* If we don't find the old_event in new_events, then we can safely delete the old_event */
00927    if (!(new_event = find_event(new_events, old_event->uid))) {
00928       old_event = destroy_event(old_event);
00929       return CMP_MATCH;
00930    }
00931 
00932    /* We have events to merge.  If any data that will affect a scheduler event has changed,
00933     * then we need to replace the scheduler event */
00934    schedule_calendar_event(old_event->owner, old_event, new_event);
00935 
00936    /* Since we don't want to mess with cancelling sched events and adding new ones, just
00937     * copy the internals of the new_event to the old_event */
00938    copy_event_data(old_event, new_event);
00939 
00940    /* Now we can go ahead and unlink the new_event from new_events and unref it so that only completely
00941     * new events remain in the container */
00942    ao2_unlink(new_events, new_event);
00943    new_event = ast_calendar_unref_event(new_event);
00944 
00945    return 0;
00946 }

static int null_chan_write ( struct ast_channel chan,
struct ast_frame frame 
) [static]

Definition at line 665 of file res_calendar.c.

00666 {
00667    return 0;
00668 }

static int reload ( void   )  [static]

Definition at line 1654 of file res_calendar.c.

References ao2_callback, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, cb_pending_deletion(), cb_rm_pending_deletion(), ast_calendar_tech::list, load_config(), load_tech_calendars(), LOG_WARNING, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, reloadlock, and ast_calendar_tech::type.

01655 {
01656    struct ast_calendar_tech *iter;
01657 
01658    ast_mutex_lock(&reloadlock);
01659 
01660    /* Mark existing calendars for deletion */
01661    ao2_callback(calendars, OBJ_NODATA | OBJ_MULTIPLE, cb_pending_deletion, NULL);
01662    load_config(1);
01663 
01664    AST_LIST_LOCK(&techs);
01665    AST_LIST_TRAVERSE(&techs, iter, list) {
01666       if (load_tech_calendars(iter)) {
01667          ast_log(LOG_WARNING, "Failed to reload %s calendars, module disabled\n", iter->type);
01668       }
01669    }
01670    AST_LIST_UNLOCK(&techs);
01671 
01672    /* Delete calendars that no longer show up in the config */
01673    ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_rm_pending_deletion, NULL);
01674 
01675    ast_mutex_unlock(&reloadlock);
01676 
01677    return 0;
01678 }

static int schedule_calendar_event ( struct ast_calendar cal,
struct ast_calendar_event old_event,
struct ast_calendar_event cmp_event 
) [static]

Definition at line 859 of file res_calendar.c.

References ast_calendar_event::alarm, ao2_lock, ao2_unlock, ast_cond_signal, ast_debug, ast_mutex_lock, ast_mutex_unlock, AST_SCHED_REPLACE, ast_tvnow(), ast_calendar::autoreminder, ast_calendar_event::bs_end_sched, ast_calendar_event::bs_start_sched, calendar_devstate_change(), calendar_event_notify(), ast_calendar_event::end, ast_calendar_event::notify_sched, refreshlock, sched, and ast_calendar_event::start.

Referenced by add_new_event_cb(), and merge_events_cb().

00860 {
00861    struct timeval now = ast_tvnow();
00862    struct ast_calendar_event *event;
00863    time_t alarm_notify_sched = 0, devstate_sched_start, devstate_sched_end;
00864    int changed = 0;
00865 
00866    event = cmp_event ? cmp_event : old_event;
00867 
00868    ao2_lock(event);
00869    if (!cmp_event || old_event->alarm != event->alarm) {
00870       changed = 1;
00871       if (cal->autoreminder) {
00872          alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000;
00873       } else if (event->alarm) {
00874          alarm_notify_sched = (event->alarm - now.tv_sec) * 1000;
00875       }
00876 
00877       /* For now, send the notification if we missed it, but the meeting hasn't happened yet */
00878       if (event->start >=  now.tv_sec) {
00879          if (alarm_notify_sched <= 0) {
00880             alarm_notify_sched = 1;
00881          }
00882          ast_mutex_lock(&refreshlock);
00883          AST_SCHED_REPLACE(old_event->notify_sched, sched, alarm_notify_sched, calendar_event_notify, old_event);
00884          ast_mutex_unlock(&refreshlock);
00885          ast_debug(3, "Calendar alarm event notification scheduled to happen in %ld ms\n", (long) alarm_notify_sched);
00886       }
00887    }
00888 
00889    if (!cmp_event || old_event->start != event->start) {
00890       changed = 1;
00891       devstate_sched_start = (event->start - now.tv_sec) * 1000;
00892 
00893       if (devstate_sched_start < 1) {
00894          devstate_sched_start = 1;
00895       }
00896 
00897       ast_mutex_lock(&refreshlock);
00898       AST_SCHED_REPLACE(old_event->bs_start_sched, sched, devstate_sched_start, calendar_devstate_change, old_event);
00899       ast_mutex_unlock(&refreshlock);
00900       ast_debug(3, "Calendar bs_start event notification scheduled to happen in %ld ms\n", (long) devstate_sched_start);
00901    }
00902 
00903    if (!cmp_event || old_event->end != event->end) {
00904       changed = 1;
00905       devstate_sched_end = (event->end - now.tv_sec) * 1000;
00906       ast_mutex_lock(&refreshlock);
00907       AST_SCHED_REPLACE(old_event->bs_end_sched, sched, devstate_sched_end, calendar_devstate_change, old_event);
00908       ast_mutex_unlock(&refreshlock);
00909       ast_debug(3, "Calendar bs_end event notification scheduled to happen in %ld ms\n", (long) devstate_sched_end);
00910    }
00911 
00912    if (changed) {
00913       ast_cond_signal(&refresh_condition);
00914    }
00915 
00916    ao2_unlock(event);
00917 
00918    return 0;
00919 }

static int unload_module ( void   )  [static]

Definition at line 1711 of file res_calendar.c.

References ao2_callback, ARRAY_LEN, ast_cli_unregister_multiple(), ast_cond_signal, ast_config_destroy(), ast_custom_function_unregister(), ast_devstate_prov_del(), AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_unload_resource(), calendar_busy_function, calendar_cli, calendar_config, calendar_event_function, calendar_query_function, calendar_query_result_function, calendar_write_function, ast_calendar_tech::list, ast_calendar_tech::module, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and refreshlock.

static struct ast_calendar* unref_calendar ( struct ast_calendar cal  )  [static]

Definition at line 254 of file res_calendar.c.

References ao2_ref.

Referenced by build_calendar(), calendar_busy_exec(), calendar_query_exec(), calendarstate(), handle_show_calendar(), handle_show_calendars(), and load_tech_calendars().

00255 {
00256    ao2_ref(cal, -1);
00257    return NULL;
00258 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk Calendar integration" , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static]

Definition at line 1786 of file res_calendar.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1786 of file res_calendar.c.

struct ast_custom_function calendar_busy_function [static]

Initial value:

 {
    .name = "CALENDAR_BUSY",
    .read = calendar_busy_exec,
}

Definition at line 1019 of file res_calendar.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry calendar_cli[] [static]

Initial value:

 {
   { .handler =  handle_show_calendar , .summary =  "Display information about a calendar" ,__VA_ARGS__ },
   { .handler =  handle_show_calendars , .summary =  "Show registered calendars" ,__VA_ARGS__ },
   { .handler =  handle_dump_sched , .summary =  "Dump calendar sched context" ,__VA_ARGS__ },
}

Definition at line 1574 of file res_calendar.c.

Referenced by load_module(), and unload_module().

struct ast_config* calendar_config [static]

Definition at line 234 of file res_calendar.c.

Referenced by load_config(), load_tech_calendars(), and unload_module().

struct ast_custom_function calendar_event_function [static]

Initial value:

 {
   .name = "CALENDAR_EVENT",
   .read = calendar_event_read,
}

Definition at line 1633 of file res_calendar.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function calendar_query_function [static]

Initial value:

 {
    .name = "CALENDAR_QUERY",
    .read = calendar_query_exec,
}

Definition at line 1204 of file res_calendar.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function calendar_query_result_function [static]

Initial value:

 {
   .name = "CALENDAR_QUERY_RESULT",
   .read = calendar_query_result_exec,
}

Definition at line 1315 of file res_calendar.c.

Referenced by load_module(), and unload_module().

struct ast_custom_function calendar_write_function [static]

Initial value:

 {
   .name = "CALENDAR_WRITE",
   .write = calendar_write_exec,
}

Definition at line 1422 of file res_calendar.c.

Referenced by load_module(), and unload_module().

struct ao2_container* calendars [static]

Definition at line 201 of file res_calendar.c.

Referenced by find_calendar().

ast_rwlock_t config_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } [static]

Definition at line 235 of file res_calendar.c.

struct ast_datastore_info event_notification_datastore [static]

Initial value:

 {
   .type = "EventNotification",
   .destroy = event_notification_destroy,
   .duplicate = event_notification_duplicate,
}

Definition at line 214 of file res_calendar.c.

Referenced by calendar_event_read(), and do_notify().

struct ast_datastore_info eventlist_datastore_info [static]

Initial value:

 {
   .type = "CalendarEventList",
   .destroy = eventlist_destroy,
   .duplicate = eventlist_duplicate,
}

Definition at line 220 of file res_calendar.c.

Referenced by calendar_query_exec(), and calendar_query_result_exec().

int module_unloading [static]

Definition at line 207 of file res_calendar.c.

struct ast_channel_tech null_tech [static]

Initial value:

 {
        .type = "NULL",
        .description = "Null channel (should not see this)",
      .write = null_chan_write,
}

Definition at line 670 of file res_calendar.c.

ast_cond_t refresh_condition [static]

Definition at line 205 of file res_calendar.c.

pthread_t refresh_thread = AST_PTHREADT_NULL [static]

Definition at line 203 of file res_calendar.c.

ast_mutex_t refreshlock [static]

Definition at line 204 of file res_calendar.c.

Referenced by caldav_load_calendar(), do_refresh(), ewscal_load_calendar(), exchangecal_load_calendar(), ical_load_calendar(), load_module(), schedule_calendar_event(), and unload_module().

ast_mutex_t reloadlock [static]

Definition at line 206 of file res_calendar.c.

struct sched_context* sched [static]

Definition at line 202 of file res_calendar.c.


Generated on Mon Oct 8 12:39:27 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7