#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_config * | ast_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_event * | ast_calendar_event_alloc (struct ast_calendar *cal) |
Allocate an astobj2 ast_calendar_event object. | |
ao2_container * | ast_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_event * | ast_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_calendar * | build_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_event * | destroy_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_calendar * | find_calendar (const char *name) |
static struct ast_calendar_event * | find_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 (void *data) |
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_calendar * | unref_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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_custom_function | calendar_busy_function |
static struct ast_cli_entry | calendar_cli [] |
static struct ast_config * | calendar_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_container * | calendars |
static ast_rwlock_t | config_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER } |
static struct ast_datastore_info | event_notification_datastore |
static struct ast_datastore_info | eventlist_datastore_info |
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_context * | sched |
Support writing attendees
Definition in file res_calendar.c.
#define CALENDAR_BUCKETS 19 |
Definition at line 165 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" |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1727 of file res_calendar.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1727 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 982 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().
00983 { 00984 struct evententry *entry, *iter; 00985 int event_startdiff = abs(start - event->start); 00986 int event_enddiff = abs(end - event->end); 00987 int i = 0; 00988 00989 if (!(entry = ast_calloc(1, sizeof(*entry)))) { 00990 ast_log(LOG_ERROR, "Unable to allocate memory for event list\n"); 00991 return -1; 00992 } 00993 00994 entry->event = event; 00995 ao2_ref(event, +1); 00996 00997 if (start == end) { 00998 AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) { 00999 int startdiff = abs(iter->event->start - start); 01000 01001 ast_debug(10, "Comparing %s with startdiff %d to %s with startdiff %d\n", event->summary, event_startdiff, iter->event->summary, startdiff); 01002 ++i; 01003 if (startdiff > event_startdiff) { 01004 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01005 return i; 01006 } 01007 if (startdiff == event_startdiff) { 01008 int enddiff = abs(iter->event->end - end); 01009 01010 if (enddiff > event_enddiff) { 01011 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01012 return i; 01013 } 01014 if (event_startdiff == enddiff) { 01015 if (strcmp(event->uid, iter->event->uid) < 0) { 01016 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01017 return i; 01018 } 01019 } 01020 } 01021 } 01022 AST_LIST_TRAVERSE_SAFE_END; 01023 01024 AST_LIST_INSERT_TAIL(events, entry, list); 01025 01026 return i; 01027 } 01028 01029 AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) { 01030 ++i; 01031 if (iter->event->start > event->start) { 01032 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01033 return i; 01034 } 01035 01036 if (iter->event->start == event->start) { 01037 if ((iter->event->end - iter->event->start) == (event->end - event->start)) { 01038 if (strcmp(event->uid, iter->event->uid) < 0) { 01039 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01040 return i; 01041 } 01042 } 01043 if ((iter->event->end - iter->event->start) < (event->end - event->start)) { 01044 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01045 return i; 01046 } 01047 } 01048 } 01049 AST_LIST_TRAVERSE_SAFE_END; 01050 01051 AST_LIST_INSERT_TAIL(events, entry, list); 01052 01053 return i; 01054 }
static int add_new_event_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 907 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().
00908 { 00909 struct ast_calendar_event *new_event = obj; 00910 struct ao2_container *events = arg; 00911 00912 ao2_link(events, new_event); 00913 schedule_calendar_event(new_event->owner, new_event, NULL); 00914 return CMP_MATCH; 00915 }
void ast_calendar_clear_events | ( | struct ast_calendar * | cal | ) |
Remove all events from calendar.
cal | calendar whose events need to be cleared |
Definition at line 555 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().
00556 { 00557 ast_debug(3, "Clearing all events for calendar %s\n", cal->name); 00558 00559 ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, clear_events_cb, NULL); 00560 }
struct ast_config* ast_calendar_config_acquire | ( | void | ) |
Grab and lock pointer to the calendar config (read only).
Definition at line 202 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().
00203 { 00204 ast_rwlock_rdlock(&config_lock); 00205 00206 if (!calendar_config) { 00207 ast_rwlock_unlock(&config_lock); 00208 return NULL; 00209 } 00210 00211 return calendar_config; 00212 }
void ast_calendar_config_release | ( | void | ) |
Release the calendar config.
Definition at line 214 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().
00215 { 00216 ast_rwlock_unlock(&config_lock); 00217 }
struct ast_calendar_event* ast_calendar_event_alloc | ( | struct ast_calendar * | cal | ) |
Allocate an astobj2 ast_calendar_event object.
cal | calendar to allocate an event for |
Definition at line 562 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().
00563 { 00564 struct ast_calendar_event *event; 00565 if (!(event = ao2_alloc(sizeof(*event), calendar_event_destructor))) { 00566 return NULL; 00567 } 00568 00569 if (ast_string_field_init(event, 32)) { 00570 event = ast_calendar_unref_event(event); 00571 return NULL; 00572 } 00573 00574 event->owner = cal; 00575 event->notify_sched = -1; 00576 event->bs_start_sched = -1; 00577 event->bs_end_sched = -1; 00578 00579 AST_LIST_HEAD_INIT_NOLOCK(&event->attendees); 00580 00581 return event; 00582 }
struct ao2_container* ast_calendar_event_container_alloc | ( | void | ) |
Allocate an astobj2 container for ast_calendar_event objects.
Definition at line 584 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().
00585 { 00586 return ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn); 00587 }
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.
cal | calendar containing the events to be merged | |
new_events | an oa2 container of events to be merged into cal->events |
Definition at line 917 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().
00918 { 00919 /* Loop through all events attached to the calendar. If there is a matching new event 00920 * merge its data over and handle any schedule changes that need to be made. Then remove 00921 * the new_event from new_events so that we are left with only new_events that we can add later. */ 00922 ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, merge_events_cb, new_events); 00923 00924 /* Now, we should only have completely new events in new_events. Loop through and add them */ 00925 ao2_callback(new_events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, add_new_event_cb, cal->events); 00926 }
int ast_calendar_register | ( | struct ast_calendar_tech * | tech | ) |
Register a new calendar technology.
tech | calendar technology to register |
0 | success | |
-1 | failure |
Definition at line 451 of file res_calendar.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_verb, ast_calendar_tech::description, ast_calendar_tech::list, load_tech_calendars(), LOG_WARNING, and ast_calendar_tech::type.
Referenced by load_module().
00452 { 00453 struct ast_calendar_tech *iter; 00454 00455 AST_LIST_LOCK(&techs); 00456 AST_LIST_TRAVERSE(&techs, iter, list) { 00457 if(!strcasecmp(tech->type, iter->type)) { 00458 ast_log(LOG_WARNING, "Already have a handler for calendar type '%s'\n", tech->type); 00459 AST_LIST_UNLOCK(&techs); 00460 return -1; 00461 } 00462 } 00463 AST_LIST_INSERT_HEAD(&techs, tech, list); 00464 AST_LIST_UNLOCK(&techs); 00465 00466 ast_verb(2, "Registered calendar type '%s' (%s)\n", tech->type, tech->description); 00467 00468 return load_tech_calendars(tech); 00469 }
struct ast_calendar_event* ast_calendar_unref_event | ( | struct ast_calendar_event * | event | ) |
Unreference an ast_calendar_event.
event | event to unref |
Definition at line 265 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().
00266 { 00267 ao2_ref(event, -1); 00268 return NULL; 00269 }
void ast_calendar_unregister | ( | struct ast_calendar_tech * | tech | ) |
Unregister a new calendar technology.
tech | calendar technology to unregister |
0 | success | |
-1 | failure |
Definition at line 483 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_verb, ast_calendar_tech::list, match_caltech_cb(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and ast_calendar_tech::type.
Referenced by load_tech_calendars(), and unload_module().
00484 { 00485 struct ast_calendar_tech *iter; 00486 00487 AST_LIST_LOCK(&techs); 00488 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, iter, list) { 00489 if (iter != tech) { 00490 continue; 00491 } 00492 00493 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, match_caltech_cb, tech); 00494 00495 AST_LIST_REMOVE_CURRENT(list); 00496 ast_verb(2, "Unregistered calendar type '%s'\n", tech->type); 00497 break; 00498 } 00499 AST_LIST_TRAVERSE_SAFE_END; 00500 AST_LIST_UNLOCK(&techs); 00501 00502 }
static struct ast_calendar* build_calendar | ( | struct ast_config * | cfg, | |
const char * | cat, | |||
const struct ast_calendar_tech * | tech | |||
) | [static] |
Definition at line 339 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().
00340 { 00341 struct ast_calendar *cal; 00342 struct ast_variable *v; 00343 int new_calendar = 0; 00344 00345 if (!(cal = find_calendar(cat))) { 00346 new_calendar = 1; 00347 if (!(cal = ao2_alloc(sizeof(*cal), calendar_destructor))) { 00348 ast_log(LOG_ERROR, "Could not allocate calendar structure. Stopping.\n"); 00349 return NULL; 00350 } 00351 00352 if (!(cal->events = ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn))) { 00353 ast_log(LOG_ERROR, "Could not allocate events container for %s\n", cat); 00354 cal = unref_calendar(cal); 00355 return NULL; 00356 } 00357 00358 if (ast_string_field_init(cal, 32)) { 00359 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", cat); 00360 cal = unref_calendar(cal); 00361 return NULL; 00362 } 00363 } else { 00364 cal->pending_deletion = 0; 00365 } 00366 00367 ast_string_field_set(cal, name, cat); 00368 cal->tech = tech; 00369 00370 cal->refresh = 3600; 00371 cal->timeframe = 60; 00372 cal->notify_waittime = 30000; 00373 00374 for (v = ast_variable_browse(cfg, cat); v; v = v->next) { 00375 if (!strcasecmp(v->name, "autoreminder")) { 00376 cal->autoreminder = atoi(v->value); 00377 } else if (!strcasecmp(v->name, "channel")) { 00378 ast_string_field_set(cal, notify_channel, v->value); 00379 } else if (!strcasecmp(v->name, "context")) { 00380 ast_string_field_set(cal, notify_context, v->value); 00381 } else if (!strcasecmp(v->name, "extension")) { 00382 ast_string_field_set(cal, notify_extension, v->value); 00383 } else if (!strcasecmp(v->name, "waittime")) { 00384 int i = atoi(v->value); 00385 if (i > 0) { 00386 cal->notify_waittime = 1000 * i; 00387 } 00388 } else if (!strcasecmp(v->name, "app")) { 00389 ast_string_field_set(cal, notify_app, v->value); 00390 } else if (!strcasecmp(v->name, "appdata")) { 00391 ast_string_field_set(cal, notify_appdata, v->value); 00392 } else if (!strcasecmp(v->name, "refresh")) { 00393 cal->refresh = atoi(v->value); 00394 } else if (!strcasecmp(v->name, "timeframe")) { 00395 cal->timeframe = atoi(v->value); 00396 } 00397 } 00398 00399 if (new_calendar) { 00400 cal->thread = AST_PTHREADT_NULL; 00401 ast_cond_init(&cal->unload, NULL); 00402 ao2_link(calendars, cal); 00403 if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) { 00404 /* If we start failing to create threads, go ahead and return NULL 00405 * and the tech module will be unregistered 00406 */ 00407 ao2_unlink(calendars, cal); 00408 cal = unref_calendar(cal); 00409 } 00410 } 00411 00412 return cal; 00413 }
static int calendar_busy_callback | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 301 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().
00302 { 00303 struct ast_calendar_event *event = obj; 00304 int *is_busy = arg; 00305 struct timeval tv = ast_tvnow(); 00306 00307 if (tv.tv_sec >= event->start && tv.tv_sec <= event->end && event->busy_state > AST_CALENDAR_BS_FREE) { 00308 *is_busy = 1; 00309 return CMP_STOP; 00310 } 00311 00312 return 0; 00313 }
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 956 of file res_calendar.c.
References ast_log(), ast_strlen_zero(), calendar_is_busy(), find_calendar(), and LOG_WARNING.
00957 { 00958 struct ast_calendar *cal; 00959 00960 if (ast_strlen_zero(data)) { 00961 ast_log(LOG_WARNING, "CALENDAR_BUSY requires an argument: CALENDAR_BUSY(<calendar_name>)\n"); 00962 return -1; 00963 } 00964 00965 cal = find_calendar(data); 00966 00967 if (!cal) { 00968 ast_log(LOG_WARNING, "Could not find calendar '%s'\n", data); 00969 return -1; 00970 } 00971 00972 strcpy(buf, calendar_is_busy(cal) ? "1" : "0"); 00973 00974 return 0; 00975 }
static int calendar_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 231 of file res_calendar.c.
References CMP_MATCH, CMP_STOP, and ast_calendar::name.
Referenced by load_module().
00232 { 00233 const struct ast_calendar *one = obj, *two = arg; 00234 return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP: 0; 00235 }
static void calendar_destructor | ( | void * | obj | ) | [static] |
Definition at line 271 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().
00272 { 00273 struct ast_calendar *cal = obj; 00274 00275 ast_debug(3, "Destroying calendar %s\n", cal->name); 00276 00277 ao2_lock(cal); 00278 cal->unloading = 1; 00279 ast_cond_signal(&cal->unload); 00280 pthread_join(cal->thread, NULL); 00281 if (cal->tech_pvt) { 00282 cal->tech_pvt = cal->tech->unref_calendar(cal->tech_pvt); 00283 } 00284 ast_calendar_clear_events(cal); 00285 ast_string_field_free_memory(cal); 00286 ao2_ref(cal->events, -1); 00287 ao2_unlock(cal); 00288 }
static int calendar_devstate_change | ( | const void * | data | ) | [static] |
Definition at line 756 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().
00757 { 00758 struct ast_calendar_event *event = (struct ast_calendar_event *)data; 00759 struct timeval now = ast_tvnow(); 00760 int is_end_event; 00761 00762 if (!event) { 00763 ast_log(LOG_WARNING, "Event was NULL!\n"); 00764 return 0; 00765 } 00766 00767 ao2_ref(event, +1); 00768 00769 is_end_event = event->end <= now.tv_sec; 00770 00771 if (is_end_event) { 00772 event->bs_end_sched = -1; 00773 } else { 00774 event->bs_start_sched = -1; 00775 } 00776 00777 /* We can have overlapping events, so ignore the event->busy_state and check busy state 00778 * based on all events in the calendar */ 00779 if (!calendar_is_busy(event->owner)) { 00780 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); 00781 } else { 00782 ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); 00783 } 00784 00785 event = ast_calendar_unref_event(event); 00786 00787 return 0; 00788 }
static void calendar_event_destructor | ( | void * | obj | ) | [static] |
Definition at line 504 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().
00505 { 00506 struct ast_calendar_event *event = obj; 00507 struct ast_calendar_attendee *attendee; 00508 00509 ast_debug(3, "Destroying event for calendar '%s'\n", event->owner->name); 00510 ast_string_field_free_memory(event); 00511 while ((attendee = AST_LIST_REMOVE_HEAD(&event->attendees, next))) { 00512 if (attendee->data) { 00513 ast_free(attendee->data); 00514 } 00515 ast_free(attendee); 00516 } 00517 }
static int calendar_event_notify | ( | const void * | data | ) | [static] |
Definition at line 732 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().
00733 { 00734 struct ast_calendar_event *event = (void *)data; 00735 int res = -1; 00736 pthread_t notify_thread = AST_PTHREADT_NULL; 00737 00738 if (!(event && event->owner)) { 00739 ast_log(LOG_ERROR, "Extremely low-cal...in fact cal is NULL!\n"); 00740 return res; 00741 } 00742 00743 ao2_ref(event, +1); 00744 event->notify_sched = -1; 00745 00746 if (ast_pthread_create_background(¬ify_thread, NULL, do_notify, event) < 0) { 00747 ast_log(LOG_ERROR, "Could not create notification thread\n"); 00748 return res; 00749 } 00750 00751 res = 0; 00752 00753 return res; 00754 }
static int calendar_event_read | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1533 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.
01534 { 01535 struct ast_datastore *datastore; 01536 struct ast_calendar_event *event; 01537 01538 if (ast_strlen_zero(data)) { 01539 ast_log(LOG_WARNING, "%s requires an argument\n", cmd); 01540 return -1; 01541 } 01542 01543 ast_channel_lock(chan); 01544 if (!(datastore = ast_channel_datastore_find(chan, &event_notification_datastore, NULL))) { 01545 ast_log(LOG_WARNING, "There is no event notification datastore on '%s'!\n", chan->name); 01546 ast_channel_unlock(chan); 01547 return -1; 01548 } 01549 ast_channel_unlock(chan); 01550 01551 if (!(event = datastore->data)) { 01552 ast_log(LOG_WARNING, "The datastore contains no data!\n"); 01553 return -1; 01554 } 01555 01556 if (!strcasecmp(data, "summary")) { 01557 ast_copy_string(buf, event->summary, len); 01558 } else if (!strcasecmp(data, "description")) { 01559 ast_copy_string(buf, event->description, len); 01560 } else if (!strcasecmp(data, "organizer")) { 01561 ast_copy_string(buf, event->organizer, len); 01562 } else if (!strcasecmp(data, "location")) { 01563 ast_copy_string(buf, event->location, len); 01564 } else if (!strcasecmp(data, "categories")) { 01565 ast_copy_string(buf, event->categories, len); 01566 } else if (!strcasecmp(data, "priority")) { 01567 snprintf(buf, len, "%d", event->priority); 01568 } else if (!strcasecmp(data, "calendar")) { 01569 ast_copy_string(buf, event->owner->name, len); 01570 } else if (!strcasecmp(data, "uid")) { 01571 ast_copy_string(buf, event->uid, len); 01572 } else if (!strcasecmp(data, "start")) { 01573 snprintf(buf, len, "%ld", (long)event->start); 01574 } else if (!strcasecmp(data, "end")) { 01575 snprintf(buf, len, "%ld", (long)event->end); 01576 } else if (!strcasecmp(data, "busystate")) { 01577 snprintf(buf, len, "%d", event->busy_state); 01578 } else if (!strcasecmp(data, "attendees")) { 01579 calendar_join_attendees(event, buf, len); 01580 } 01581 01582 01583 return 0; 01584 }
static int calendar_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 225 of file res_calendar.c.
References ast_str_case_hash(), and ast_calendar::name.
Referenced by load_module().
00226 { 00227 const struct ast_calendar *cal = obj; 00228 return ast_str_case_hash(cal->name); 00229 }
static int calendar_is_busy | ( | struct ast_calendar * | cal | ) | [static] |
Definition at line 315 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().
00316 { 00317 int is_busy = 0; 00318 00319 ao2_callback(cal->events, OBJ_NODATA, calendar_busy_callback, &is_busy); 00320 00321 return is_busy; 00322 }
static void calendar_join_attendees | ( | struct ast_calendar_event * | event, | |
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1162 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().
01163 { 01164 struct ast_str *tmp; 01165 struct ast_calendar_attendee *attendee; 01166 01167 if (!(tmp = ast_str_create(32))) { 01168 ast_log(LOG_ERROR, "Could not allocate memory for attendees!\n"); 01169 return; 01170 } 01171 01172 AST_LIST_TRAVERSE(&event->attendees, attendee, next) { 01173 ast_str_append(&tmp, 0, "%s%s", attendee == AST_LIST_FIRST(&event->attendees) ? "" : ",", attendee->data); 01174 } 01175 01176 ast_copy_string(buf, ast_str_buffer(tmp), len); 01177 ast_free(tmp); 01178 }
static int calendar_query_exec | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1076 of file res_calendar.c.
References add_event_to_list(), ao2_alloc, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, 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().
01077 { 01078 struct ast_calendar *cal; 01079 struct ao2_iterator i; 01080 struct ast_calendar_event *event; 01081 struct eventlist *events; 01082 time_t start = INT_MIN, end = INT_MAX; 01083 struct ast_datastore *eventlist_datastore; 01084 AST_DECLARE_APP_ARGS(args, 01085 AST_APP_ARG(calendar); 01086 AST_APP_ARG(start); 01087 AST_APP_ARG(end); 01088 ); 01089 01090 if (!chan) { 01091 ast_log(LOG_WARNING, "%s requires a channel to store the data on\n", cmd); 01092 return -1; 01093 } 01094 01095 AST_STANDARD_APP_ARGS(args, data); 01096 01097 if (ast_strlen_zero(args.calendar)) { 01098 ast_log(LOG_WARNING, "%s requires a calendar argument\n", cmd); 01099 return -1; 01100 } 01101 01102 if (!(cal = find_calendar(args.calendar))) { 01103 ast_log(LOG_WARNING, "Unknown calendar '%s'\n", args.calendar); 01104 return -1; 01105 } 01106 01107 if (!(events = ao2_alloc(sizeof(*events), eventlist_destructor))) { 01108 ast_log(LOG_ERROR, "Unable to allocate memory for event list\n"); 01109 cal = unref_calendar(cal); 01110 return -1; 01111 } 01112 01113 if (!ast_strlen_zero(args.start)) { 01114 start = atoi(args.start); 01115 } 01116 01117 if (!ast_strlen_zero(args.end)) { 01118 end = atoi(args.end); 01119 } 01120 01121 i = ao2_iterator_init(cal->events, 0); 01122 while ((event = ao2_iterator_next(&i))) { 01123 if (!(start > event->end || end < event->start)) { 01124 ast_debug(10, "%s (%ld - %ld) overlapped with (%ld - %ld)\n", event->summary, (long) event->start, (long) event->end, (long) start, (long) end); 01125 if (add_event_to_list(events, event, start, end) < 0) { 01126 event = ast_calendar_unref_event(event); 01127 ao2_iterator_destroy(&i); 01128 return -1; 01129 } 01130 } 01131 01132 event = ast_calendar_unref_event(event); 01133 } 01134 ao2_iterator_destroy(&i); 01135 01136 ast_channel_lock(chan); 01137 do { 01138 generate_random_string(buf, len); 01139 } while (ast_channel_datastore_find(chan, &eventlist_datastore_info, buf)); 01140 ast_channel_unlock(chan); 01141 01142 if (!(eventlist_datastore = ast_datastore_alloc(&eventlist_datastore_info, buf))) { 01143 ast_log(LOG_ERROR, "Could not allocate datastore!\n"); 01144 return -1; 01145 } 01146 01147 eventlist_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01148 eventlist_datastore->data = events; 01149 01150 ast_channel_lock(chan); 01151 ast_channel_datastore_add(chan, eventlist_datastore); 01152 ast_channel_unlock(chan); 01153 01154 return 0; 01155 }
static int calendar_query_result_exec | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 1180 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.
01181 { 01182 struct ast_datastore *datastore; 01183 struct eventlist *events; 01184 struct evententry *entry; 01185 int row = 1; 01186 size_t listlen = 0; 01187 AST_DECLARE_APP_ARGS(args, 01188 AST_APP_ARG(id); 01189 AST_APP_ARG(field); 01190 AST_APP_ARG(row); 01191 ); 01192 01193 if (!chan) { 01194 ast_log(LOG_WARNING, "%s requires a channel\n", cmd); 01195 return -1; 01196 } 01197 01198 AST_STANDARD_APP_ARGS(args, data); 01199 01200 if (ast_strlen_zero(args.id) || ast_strlen_zero(args.field)) { 01201 ast_log(LOG_WARNING, "%s requires an id and a field", cmd); 01202 return -1; 01203 } 01204 01205 ast_channel_lock(chan); 01206 if (!(datastore = ast_channel_datastore_find(chan, &eventlist_datastore_info, args.id))) { 01207 ast_log(LOG_WARNING, "There is no event notification datastore with id '%s' on '%s'!\n", args.id, chan->name); 01208 ast_channel_unlock(chan); 01209 return -1; 01210 } 01211 ast_channel_unlock(chan); 01212 01213 if (!(events = datastore->data)) { 01214 ast_log(LOG_WARNING, "The datastore contains no data!\n"); 01215 return -1; 01216 } 01217 01218 if (!ast_strlen_zero(args.row)) { 01219 row = atoi(args.row); 01220 } 01221 01222 AST_LIST_TRAVERSE(events, entry, list) { 01223 listlen++; 01224 } 01225 01226 if (!strcasecmp(args.field, "getnum")) { 01227 snprintf(buf, len, "%zu", listlen); 01228 return 0; 01229 } 01230 01231 AST_LIST_TRAVERSE(events, entry, list) { 01232 if (--row) { 01233 continue; 01234 } 01235 if (!strcasecmp(args.field, "summary")) { 01236 ast_copy_string(buf, entry->event->summary, len); 01237 } else if (!strcasecmp(args.field, "description")) { 01238 ast_copy_string(buf, entry->event->description, len); 01239 } else if (!strcasecmp(args.field, "organizer")) { 01240 ast_copy_string(buf, entry->event->organizer, len); 01241 } else if (!strcasecmp(args.field, "location")) { 01242 ast_copy_string(buf, entry->event->location, len); 01243 } else if (!strcasecmp(args.field, "categories")) { 01244 ast_copy_string(buf, entry->event->categories, len); 01245 } else if (!strcasecmp(args.field, "priority")) { 01246 snprintf(buf, len, "%d", entry->event->priority); 01247 } else if (!strcasecmp(args.field, "calendar")) { 01248 ast_copy_string(buf, entry->event->owner->name, len); 01249 } else if (!strcasecmp(args.field, "uid")) { 01250 ast_copy_string(buf, entry->event->uid, len); 01251 } else if (!strcasecmp(args.field, "start")) { 01252 snprintf(buf, len, "%ld", (long) entry->event->start); 01253 } else if (!strcasecmp(args.field, "end")) { 01254 snprintf(buf, len, "%ld", (long) entry->event->end); 01255 } else if (!strcasecmp(args.field, "busystate")) { 01256 snprintf(buf, len, "%d", entry->event->busy_state); 01257 } else if (!strcasecmp(args.field, "attendees")) { 01258 calendar_join_attendees(entry->event, buf, len); 01259 } else { 01260 ast_log(LOG_WARNING, "Unknown field '%s'\n", args.field); 01261 } 01262 break; 01263 } 01264 01265 return 0; 01266 }
static int calendar_write_exec | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 1273 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.
01274 { 01275 int i, j, ret = -1; 01276 char *val_dup = NULL; 01277 struct ast_calendar *cal = NULL; 01278 struct ast_calendar_event *event = NULL; 01279 struct timeval tv = ast_tvnow(); 01280 AST_DECLARE_APP_ARGS(fields, 01281 AST_APP_ARG(field)[10]; 01282 ); 01283 AST_DECLARE_APP_ARGS(values, 01284 AST_APP_ARG(value)[10]; 01285 ); 01286 01287 if (!(val_dup = ast_strdup(value))) { 01288 ast_log(LOG_ERROR, "Could not allocate memory for values\n"); 01289 return -1; 01290 } 01291 01292 AST_STANDARD_APP_ARGS(fields, data); 01293 AST_STANDARD_APP_ARGS(values, val_dup); 01294 01295 /* XXX Eventually we will support unnamed calendars, so if we don't find one, we parse 01296 * for a calendar type and create it */ 01297 if (!(cal = find_calendar(fields.field[0]))) { 01298 ast_log(LOG_WARNING, "Couldn't find calendar '%s'\n", fields.field[0]); 01299 goto write_cleanup; 01300 } 01301 01302 if (!(cal->tech->write_event)) { 01303 ast_log(LOG_WARNING, "Calendar '%s' has no write function!\n", cal->name); 01304 goto write_cleanup; 01305 } 01306 01307 if (!(event = ast_calendar_event_alloc(cal))) { 01308 goto write_cleanup; 01309 } 01310 01311 if (ast_strlen_zero(fields.field[0])) { 01312 ast_log(LOG_WARNING, "CALENDAR_WRITE requires a calendar name!\n"); 01313 goto write_cleanup; 01314 } 01315 01316 if (fields.argc - 1 != values.argc) { 01317 ast_log(LOG_WARNING, "CALENDAR_WRITE should have the same number of fields (%d) and values (%d)!\n", fields.argc - 1, values.argc); 01318 goto write_cleanup; 01319 } 01320 01321 event->owner = cal; 01322 01323 for (i = 1, j = 0; i < fields.argc; i++, j++) { 01324 if (!strcasecmp(fields.field[i], "summary")) { 01325 ast_string_field_set(event, summary, values.value[j]); 01326 } else if (!strcasecmp(fields.field[i], "description")) { 01327 ast_string_field_set(event, description, values.value[j]); 01328 } else if (!strcasecmp(fields.field[i], "organizer")) { 01329 ast_string_field_set(event, organizer, values.value[j]); 01330 } else if (!strcasecmp(fields.field[i], "location")) { 01331 ast_string_field_set(event, location, values.value[j]); 01332 } else if (!strcasecmp(fields.field[i], "categories")) { 01333 ast_string_field_set(event, categories, values.value[j]); 01334 } else if (!strcasecmp(fields.field[i], "priority")) { 01335 event->priority = atoi(values.value[j]); 01336 } else if (!strcasecmp(fields.field[i], "uid")) { 01337 ast_string_field_set(event, uid, values.value[j]); 01338 } else if (!strcasecmp(fields.field[i], "start")) { 01339 event->start = atoi(values.value[j]); 01340 } else if (!strcasecmp(fields.field[i], "end")) { 01341 event->end = atoi(values.value[j]); 01342 } else if (!strcasecmp(fields.field[i], "busystate")) { 01343 event->busy_state = atoi(values.value[j]); 01344 } else { 01345 ast_log(LOG_WARNING, "Unknown calendar event field '%s'\n", fields.field[i]); 01346 } 01347 } 01348 01349 if (!event->start) { 01350 event->start = tv.tv_sec; 01351 } 01352 01353 if (!event->end) { 01354 event->end = tv.tv_sec; 01355 } 01356 01357 if((ret = cal->tech->write_event(event))) { 01358 ast_log(LOG_WARNING, "Writing event to calendar '%s' failed!\n", cal->name); 01359 } 01360 01361 write_cleanup: 01362 if (cal) { 01363 cal = unref_calendar(cal); 01364 } 01365 if (event) { 01366 event = ast_calendar_unref_event(event); 01367 } 01368 if (val_dup) { 01369 ast_free(val_dup); 01370 } 01371 01372 return ret; 01373 }
static enum ast_device_state calendarstate | ( | const char * | data | ) | [static] |
Definition at line 324 of file res_calendar.c.
References AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, ast_strlen_zero(), calendar_is_busy(), find_calendar(), ast_calendar_tech::is_busy, and ast_calendar::tech.
Referenced by load_module().
00325 { 00326 struct ast_calendar *cal; 00327 00328 if (ast_strlen_zero(data) || (!(cal = find_calendar(data)))) { 00329 return AST_DEVICE_INVALID; 00330 } 00331 00332 if (cal->tech->is_busy) { 00333 return cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; 00334 } 00335 00336 return calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; 00337 }
static int cb_pending_deletion | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1591 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::pending_deletion.
Referenced by reload().
01592 { 01593 struct ast_calendar *cal = user_data; 01594 01595 cal->pending_deletion = 1; 01596 01597 return CMP_MATCH; 01598 }
static int cb_rm_pending_deletion | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1600 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::pending_deletion.
Referenced by reload().
01601 { 01602 struct ast_calendar *cal = user_data; 01603 01604 return cal->pending_deletion ? CMP_MATCH : 0; 01605 }
static int clear_events_cb | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 546 of file res_calendar.c.
References CMP_MATCH, and destroy_event().
Referenced by ast_calendar_clear_events().
00547 { 00548 struct ast_calendar_event *event = user_data; 00549 00550 event = destroy_event(event); 00551 00552 return CMP_MATCH; 00553 }
static void copy_event_data | ( | struct ast_calendar_event * | dst, | |
struct ast_calendar_event * | src | |||
) | [static] |
Definition at line 790 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().
00791 { 00792 struct ast_calendar_attendee *attendee; 00793 00794 ast_string_field_set(dst, summary, src->summary); 00795 ast_string_field_set(dst, description, src->description); 00796 ast_string_field_set(dst, organizer, src->organizer); 00797 ast_string_field_set(dst, location, src->location); 00798 ast_string_field_set(dst, uid, src->uid); 00799 ast_string_field_set(dst, categories, src->categories); 00800 dst->priority = src->priority; 00801 dst->owner = src->owner; 00802 dst->start = src->start; 00803 dst->end = src->end; 00804 dst->alarm = src->alarm; 00805 dst->busy_state = src->busy_state; 00806 00807 /* Delete any existing attendees */ 00808 while ((attendee = AST_LIST_REMOVE_HEAD(&dst->attendees, next))) { 00809 ast_free(attendee); 00810 } 00811 00812 /* Copy over the new attendees */ 00813 while ((attendee = AST_LIST_REMOVE_HEAD(&src->attendees, next))) { 00814 AST_LIST_INSERT_TAIL(&dst->attendees, attendee, next); 00815 } 00816 }
static struct ast_calendar_event* destroy_event | ( | struct ast_calendar_event * | event | ) | [static] |
Definition at line 521 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().
00522 { 00523 if (event->notify_sched > -1 && ast_sched_del(sched, event->notify_sched)) { 00524 ast_debug(3, "Notification running, can't delete sched entry\n"); 00525 } 00526 if (event->bs_start_sched > -1 && ast_sched_del(sched, event->bs_start_sched)) { 00527 ast_debug(3, "Devicestate update (start) running, can't delete sched entry\n"); 00528 } 00529 if (event->bs_end_sched > -1 && ast_sched_del(sched, event->bs_end_sched)) { 00530 ast_debug(3, "Devicestate update (end) running, can't delete sched entry\n"); 00531 } 00532 00533 /* If an event is being deleted and we've fired an event changing the status at the beginning, 00534 * but haven't hit the end event yet, go ahead and set the devicestate to the current busy status */ 00535 if (event->bs_start_sched < 0 && event->bs_end_sched >= 0) { 00536 if (!calendar_is_busy(event->owner)) { 00537 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); 00538 } else { 00539 ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); 00540 } 00541 } 00542 00543 return NULL; 00544 }
static void* do_notify | ( | void * | data | ) | [static] |
Definition at line 635 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().
00636 { 00637 struct ast_calendar_event *event = data; 00638 struct ast_dial *dial = NULL; 00639 struct ast_str *apptext = NULL; 00640 struct ast_datastore *datastore; 00641 enum ast_dial_result res; 00642 struct ast_channel *chan = NULL; 00643 char *tech, *dest; 00644 char buf[8]; 00645 00646 tech = ast_strdupa(event->owner->notify_channel); 00647 00648 if ((dest = strchr(tech, '/'))) { 00649 *dest = '\0'; 00650 dest++; 00651 } else { 00652 ast_log(LOG_WARNING, "Channel should be in form Tech/Dest (was '%s')\n", tech); 00653 goto notify_cleanup; 00654 } 00655 00656 if (!(dial = ast_dial_create())) { 00657 ast_log(LOG_ERROR, "Could not create dial structure\n"); 00658 goto notify_cleanup; 00659 } 00660 00661 if (ast_dial_append(dial, tech, dest) < 0) { 00662 ast_log(LOG_ERROR, "Could not append channel\n"); 00663 goto notify_cleanup; 00664 } 00665 00666 ast_dial_set_global_timeout(dial, event->owner->notify_waittime); 00667 generate_random_string(buf, sizeof(buf)); 00668 00669 if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, 0, 0, 0, 0, 0, 0, 0, "Calendar/%s-%s", event->owner->name, buf))) { 00670 ast_log(LOG_ERROR, "Could not allocate notification channel\n"); 00671 goto notify_cleanup; 00672 } 00673 00674 chan->tech = &null_tech; 00675 chan->nativeformats = chan->writeformat = chan->rawwriteformat = 00676 chan->readformat = chan->rawreadformat = AST_FORMAT_SLINEAR; 00677 00678 if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) { 00679 ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n"); 00680 goto notify_cleanup; 00681 } 00682 00683 datastore->data = event; 00684 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 00685 00686 ao2_ref(event, +1); 00687 res = ast_channel_datastore_add(chan, datastore); 00688 00689 if (!(apptext = ast_str_create(32))) { 00690 goto notify_cleanup; 00691 } 00692 00693 if (!ast_strlen_zero(event->owner->notify_app)) { 00694 ast_str_set(&apptext, 0, "%s,%s", event->owner->notify_app, event->owner->notify_appdata); 00695 ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, ast_str_buffer(apptext)); 00696 } else { 00697 } 00698 00699 ast_verb(3, "Dialing %s for notification on calendar %s\n", event->owner->notify_channel, event->owner->name); 00700 res = ast_dial_run(dial, chan, 0); 00701 00702 if (res != AST_DIAL_RESULT_ANSWERED) { 00703 ast_verb(3, "Notification call for %s was not completed\n", event->owner->name); 00704 } else { 00705 struct ast_channel *answered; 00706 00707 answered = ast_dial_answered_steal(dial); 00708 if (ast_strlen_zero(event->owner->notify_app)) { 00709 ast_copy_string(answered->context, event->owner->notify_context, sizeof(answered->context)); 00710 ast_copy_string(answered->exten, event->owner->notify_extension, sizeof(answered->exten)); 00711 answered->priority = 1; 00712 ast_pbx_run(answered); 00713 } 00714 } 00715 00716 notify_cleanup: 00717 if (apptext) { 00718 ast_free(apptext); 00719 } 00720 if (dial) { 00721 ast_dial_destroy(dial); 00722 } 00723 if (chan) { 00724 ast_channel_release(chan); 00725 } 00726 00727 event = ast_calendar_unref_event(event); 00728 00729 return NULL; 00730 }
static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 1633 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.
01634 { 01635 for (;;) { 01636 struct timeval now = ast_tvnow(); 01637 struct timespec ts = {0,}; 01638 int res, wait; 01639 01640 ast_mutex_lock(&refreshlock); 01641 01642 if ((wait = ast_sched_wait(sched)) < 0) { 01643 wait = 1000; 01644 } 01645 01646 ts.tv_sec = (now.tv_sec + wait / 1000) + 1; 01647 res = ast_cond_timedwait(&refresh_condition, &refreshlock, &ts); 01648 01649 ast_mutex_unlock(&refreshlock); 01650 01651 ast_sched_runq(sched); 01652 } 01653 01654 return NULL; 01655 }
static char* epoch_to_string | ( | char * | buf, | |
size_t | buflen, | |||
time_t | epoch | |||
) | [static] |
Definition at line 1411 of file res_calendar.c.
References ast_localtime(), and ast_strftime().
Referenced by handle_show_calendar().
01412 { 01413 struct ast_tm tm; 01414 struct timeval tv = { 01415 .tv_sec = epoch, 01416 }; 01417 01418 if (!epoch) { 01419 *buf = '\0'; 01420 return buf; 01421 } 01422 ast_localtime(&tv, &tm, NULL); 01423 ast_strftime(buf, buflen, "%F %r %z", &tm); 01424 01425 return buf; 01426 }
static int event_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 251 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().
00252 { 00253 const struct ast_calendar_event *one = obj, *two = arg; 00254 return !strcmp(one->uid, two->uid) ? CMP_MATCH | CMP_STOP : 0; 00255 }
static int event_hash_fn | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 245 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().
00246 { 00247 const struct ast_calendar_event *event = obj; 00248 return ast_str_hash(event->uid); 00249 }
static void event_notification_destroy | ( | void * | data | ) | [static] |
Definition at line 589 of file res_calendar.c.
References ast_calendar_unref_event().
00590 { 00591 struct ast_calendar_event *event = data; 00592 00593 event = ast_calendar_unref_event(event); 00594 00595 }
static void * event_notification_duplicate | ( | void * | data | ) | [static] |
Definition at line 597 of file res_calendar.c.
References ao2_ref.
00598 { 00599 struct ast_calendar_event *event = data; 00600 00601 if (!event) { 00602 return NULL; 00603 } 00604 00605 ao2_ref(event, +1); 00606 00607 return event; 00608 }
static void eventlist_destroy | ( | void * | data | ) | [static] |
static void eventlist_destructor | ( | void * | obj | ) | [static] |
Definition at line 290 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().
00291 { 00292 struct eventlist *events = obj; 00293 struct evententry *entry; 00294 00295 while ((entry = AST_LIST_REMOVE_HEAD(events, list))) { 00296 ao2_ref(entry->event, -1); 00297 ast_free(entry); 00298 } 00299 }
static void * eventlist_duplicate | ( | void * | data | ) | [static] |
static struct ast_calendar* find_calendar | ( | const char * | name | ) | [static] |
Definition at line 237 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().
00238 { 00239 struct ast_calendar tmp = { 00240 .name = name, 00241 }; 00242 return ao2_find(calendars, &tmp, OBJ_POINTER); 00243 }
static struct ast_calendar_event* find_event | ( | struct ao2_container * | events, | |
const char * | uid | |||
) | [static] |
Definition at line 257 of file res_calendar.c.
References ao2_find, events, OBJ_POINTER, and ast_calendar_event::uid.
Referenced by merge_events_cb().
00258 { 00259 struct ast_calendar_event tmp = { 00260 .uid = uid, 00261 }; 00262 return ao2_find(events, &tmp, OBJ_POINTER); 00263 }
static char* generate_random_string | ( | char * | buf, | |
size_t | size | |||
) | [static] |
Generate 32 byte random string (stolen from chan_sip.c).
Definition at line 611 of file res_calendar.c.
References ast_random().
00612 { 00613 long val[4]; 00614 int x; 00615 00616 for (x = 0; x < 4; x++) { 00617 val[x] = ast_random(); 00618 } 00619 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 00620 00621 return buf; 00622 }
static char* handle_dump_sched | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1508 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.
01509 { 01510 switch(cmd) { 01511 case CLI_INIT: 01512 e->command = "calendar dump sched"; 01513 e->usage = 01514 "Usage: calendar dump sched\n" 01515 " Dump the calendar sched context"; 01516 return NULL; 01517 01518 case CLI_GENERATE: 01519 return NULL; 01520 } 01521 01522 ast_sched_dump(sched); 01523 01524 return CLI_SUCCESS; 01525 }
static char* handle_show_calendar | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1428 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.
01429 { 01430 #define FORMAT "%-17.17s : %-20.20s\n" 01431 #define FORMAT2 "%-12.12s: %-40.60s\n" 01432 struct ao2_iterator i; 01433 struct ast_calendar *cal; 01434 struct ast_calendar_event *event; 01435 int which = 0; 01436 char *ret = NULL; 01437 01438 switch(cmd) { 01439 case CLI_INIT: 01440 e->command = "calendar show calendar"; 01441 e->usage = 01442 "Usage: calendar show calendar <calendar name>\n" 01443 " Displays information about a calendar\n"; 01444 return NULL; 01445 01446 case CLI_GENERATE: 01447 if (a->pos != 3) { 01448 return NULL; 01449 } 01450 i = ao2_iterator_init(calendars, 0); 01451 while ((cal = ao2_iterator_next(&i))) { 01452 if (!strncasecmp(a->word, cal->name, strlen(a->word)) && ++which > a->n) { 01453 ret = ast_strdup(cal->name); 01454 cal = unref_calendar(cal); 01455 break; 01456 } 01457 cal = unref_calendar(cal); 01458 } 01459 ao2_iterator_destroy(&i); 01460 return ret; 01461 } 01462 01463 if (a->argc != 4) { 01464 return CLI_SHOWUSAGE; 01465 } 01466 01467 if (!(cal = find_calendar(a->argv[3]))) { 01468 return NULL; 01469 } 01470 01471 ast_cli(a->fd, FORMAT, "Name", cal->name); 01472 ast_cli(a->fd, FORMAT, "Notify channel", cal->notify_channel); 01473 ast_cli(a->fd, FORMAT, "Notify context", cal->notify_context); 01474 ast_cli(a->fd, FORMAT, "Notify extension", cal->notify_extension); 01475 ast_cli(a->fd, FORMAT, "Notify application", cal->notify_app); 01476 ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata); 01477 ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh); 01478 ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe); 01479 ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder); 01480 ast_cli(a->fd, "%s\n", "Events"); 01481 ast_cli(a->fd, "%s\n", "------"); 01482 01483 i = ao2_iterator_init(cal->events, 0); 01484 while ((event = ao2_iterator_next(&i))) { 01485 char buf[100]; 01486 01487 ast_cli(a->fd, FORMAT2, "Summary", event->summary); 01488 ast_cli(a->fd, FORMAT2, "Description", event->description); 01489 ast_cli(a->fd, FORMAT2, "Organizer", event->organizer); 01490 ast_cli(a->fd, FORMAT2, "Location", event->location); 01491 ast_cli(a->fd, FORMAT2, "Cartegories", event->categories); 01492 ast_cli(a->fd, "%-12.12s: %d\n", "Priority", event->priority); 01493 ast_cli(a->fd, FORMAT2, "UID", event->uid); 01494 ast_cli(a->fd, FORMAT2, "Start", epoch_to_string(buf, sizeof(buf), event->start)); 01495 ast_cli(a->fd, FORMAT2, "End", epoch_to_string(buf, sizeof(buf), event->end)); 01496 ast_cli(a->fd, FORMAT2, "Alarm", epoch_to_string(buf, sizeof(buf), event->alarm)); 01497 ast_cli(a->fd, "\n"); 01498 01499 event = ast_calendar_unref_event(event); 01500 } 01501 ao2_iterator_destroy(&i); 01502 cal = unref_calendar(cal); 01503 return CLI_SUCCESS; 01504 #undef FORMAT 01505 #undef FORMAT2 01506 }
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 1381 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.
01382 { 01383 #define FORMAT "%-20.20s %-10.10s %-6.6s\n" 01384 struct ao2_iterator i; 01385 struct ast_calendar *cal; 01386 01387 switch(cmd) { 01388 case CLI_INIT: 01389 e->command = "calendar show calendars"; 01390 e->usage = 01391 "Usage: calendar show calendars\n" 01392 " Lists all registered calendars.\n"; 01393 return NULL; 01394 case CLI_GENERATE: 01395 return NULL; 01396 } 01397 01398 ast_cli(a->fd, FORMAT, "Calendar", "Type", "Status"); 01399 ast_cli(a->fd, FORMAT, "--------", "----", "------"); 01400 i = ao2_iterator_init(calendars, 0); 01401 while ((cal = ao2_iterator_next(&i))) { 01402 ast_cli(a->fd, FORMAT, cal->name, cal->tech->type, calendar_is_busy(cal) ? "busy" : "free"); 01403 cal = unref_calendar(cal); 01404 } 01405 ao2_iterator_destroy(&i); 01406 01407 return CLI_SUCCESS; 01408 #undef FORMAT 01409 }
static int load_config | ( | void * | data | ) | [static] |
Definition at line 929 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_flags, config_lock, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, and LOG_ERROR.
00930 { 00931 struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; 00932 struct ast_config *tmpcfg; 00933 00934 if (!(tmpcfg = ast_config_load2("calendar.conf", "calendar", config_flags)) || 00935 tmpcfg == CONFIG_STATUS_FILEINVALID) { 00936 ast_log(LOG_ERROR, "Unable to load config calendar.conf\n"); 00937 return -1; 00938 } 00939 00940 if (tmpcfg == CONFIG_STATUS_FILEUNCHANGED) { 00941 return 0; 00942 } 00943 00944 ast_rwlock_wrlock(&config_lock); 00945 if (calendar_config) { 00946 ast_config_destroy(calendar_config); 00947 } 00948 00949 calendar_config = tmpcfg; 00950 ast_rwlock_unlock(&config_lock); 00951 00952 return 0; 00953 }
static int load_module | ( | void | ) | [static] |
Definition at line 1683 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_module_ref(), 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().
01684 { 01685 if (!(calendars = ao2_container_alloc(CALENDAR_BUCKETS, calendar_hash_fn, calendar_cmp_fn))) { 01686 ast_log(LOG_ERROR, "Unable to allocate calendars container!\n"); 01687 return AST_MODULE_LOAD_FAILURE; 01688 } 01689 01690 if (load_config(NULL)) { 01691 /* We don't have calendar support enabled */ 01692 return AST_MODULE_LOAD_DECLINE; 01693 } 01694 01695 ast_mutex_init(&refreshlock); 01696 ast_cond_init(&refresh_condition, NULL); 01697 ast_mutex_init(&reloadlock); 01698 01699 if (!(sched = sched_context_create())) { 01700 ast_log(LOG_ERROR, "Unable to create sched context\n"); 01701 return AST_MODULE_LOAD_FAILURE; 01702 } 01703 01704 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 01705 ast_log(LOG_ERROR, "Unable to start refresh thread--notifications disabled!\n"); 01706 } 01707 01708 ast_custom_function_register(&calendar_busy_function); 01709 ast_custom_function_register(&calendar_event_function); 01710 ast_custom_function_register(&calendar_query_function); 01711 ast_custom_function_register(&calendar_query_result_function); 01712 ast_custom_function_register(&calendar_write_function); 01713 ast_cli_register_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01714 01715 ast_devstate_prov_add("Calendar", calendarstate); 01716 01717 /* Since other modules depend on this, disable unloading */ 01718 ast_module_ref(ast_module_info->self); 01719 01720 return AST_MODULE_LOAD_SUCCESS; 01721 }
static int load_tech_calendars | ( | struct ast_calendar_tech * | tech | ) | [static] |
Definition at line 415 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().
00416 { 00417 struct ast_calendar *cal; 00418 const char *cat = NULL; 00419 const char *val; 00420 00421 if (!calendar_config) { 00422 ast_log(LOG_WARNING, "Calendar support disabled, not loading %s calendar module\n", tech->type); 00423 return -1; 00424 } 00425 00426 ast_rwlock_wrlock(&config_lock); 00427 while ((cat = ast_category_browse(calendar_config, cat))) { 00428 if (!strcasecmp(cat, "general")) { 00429 continue; 00430 } 00431 00432 if (!(val = ast_variable_retrieve(calendar_config, cat, "type")) || strcasecmp(val, tech->type)) { 00433 continue; 00434 } 00435 00436 /* A serious error occurred loading calendars from this tech and it should be disabled */ 00437 if (!(cal = build_calendar(calendar_config, cat, tech))) { 00438 ast_calendar_unregister(tech); 00439 ast_rwlock_unlock(&config_lock); 00440 return -1; 00441 } 00442 00443 cal = unref_calendar(cal); 00444 } 00445 00446 ast_rwlock_unlock(&config_lock); 00447 00448 return 0; 00449 }
static int match_caltech_cb | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 471 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::tech.
Referenced by ast_calendar_unregister().
00472 { 00473 struct ast_calendar *cal = user_data; 00474 struct ast_calendar_tech *tech = arg; 00475 00476 if (cal->tech == tech) { 00477 return CMP_MATCH; 00478 } 00479 00480 return 0; 00481 }
static int merge_events_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 880 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().
00881 { 00882 struct ast_calendar_event *old_event = obj, *new_event; 00883 struct ao2_container *new_events = arg; 00884 00885 /* If we don't find the old_event in new_events, then we can safely delete the old_event */ 00886 if (!(new_event = find_event(new_events, old_event->uid))) { 00887 old_event = destroy_event(old_event); 00888 return CMP_MATCH; 00889 } 00890 00891 /* We have events to merge. If any data that will affect a scheduler event has changed, 00892 * then we need to replace the scheduler event */ 00893 schedule_calendar_event(old_event->owner, old_event, new_event); 00894 00895 /* Since we don't want to mess with cancelling sched events and adding new ones, just 00896 * copy the internals of the new_event to the old_event */ 00897 copy_event_data(old_event, new_event); 00898 00899 /* Now we can go ahead and unlink the new_event from new_events and unref it so that only completely 00900 * new events remain in the container */ 00901 ao2_unlink(new_events, new_event); 00902 new_event = ast_calendar_unref_event(new_event); 00903 00904 return 0; 00905 }
static int null_chan_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | frame | |||
) | [static] |
static int reload | ( | void | ) | [static] |
Definition at line 1607 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.
01608 { 01609 struct ast_calendar_tech *iter; 01610 01611 ast_mutex_lock(&reloadlock); 01612 01613 /* Mark existing calendars for deletion */ 01614 ao2_callback(calendars, OBJ_NODATA | OBJ_MULTIPLE, cb_pending_deletion, NULL); 01615 load_config(NULL); 01616 01617 AST_LIST_LOCK(&techs); 01618 AST_LIST_TRAVERSE(&techs, iter, list) { 01619 if (load_tech_calendars(iter)) { 01620 ast_log(LOG_WARNING, "Failed to reload %s calendars, module disabled\n", iter->type); 01621 } 01622 } 01623 AST_LIST_UNLOCK(&techs); 01624 01625 /* Delete calendars that no longer show up in the config */ 01626 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_rm_pending_deletion, NULL); 01627 01628 ast_mutex_unlock(&reloadlock); 01629 01630 return 0; 01631 }
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 818 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().
00819 { 00820 struct timeval now = ast_tvnow(); 00821 struct ast_calendar_event *event; 00822 time_t alarm_notify_sched = 0, devstate_sched_start, devstate_sched_end; 00823 int changed = 0; 00824 00825 event = cmp_event ? cmp_event : old_event; 00826 00827 ao2_lock(event); 00828 if (!cmp_event || old_event->alarm != event->alarm) { 00829 changed = 1; 00830 if (cal->autoreminder) { 00831 alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000; 00832 } else if (event->alarm) { 00833 alarm_notify_sched = (event->alarm - now.tv_sec) * 1000; 00834 } 00835 00836 /* For now, send the notification if we missed it, but the meeting hasn't happened yet */ 00837 if (event->start >= now.tv_sec) { 00838 if (alarm_notify_sched <= 0) { 00839 alarm_notify_sched = 1; 00840 } 00841 ast_mutex_lock(&refreshlock); 00842 AST_SCHED_REPLACE(old_event->notify_sched, sched, alarm_notify_sched, calendar_event_notify, old_event); 00843 ast_mutex_unlock(&refreshlock); 00844 ast_debug(3, "Calendar alarm event notification scheduled to happen in %ld ms\n", (long) alarm_notify_sched); 00845 } 00846 } 00847 00848 if (!cmp_event || old_event->start != event->start) { 00849 changed = 1; 00850 devstate_sched_start = (event->start - now.tv_sec) * 1000; 00851 00852 if (devstate_sched_start < 1) { 00853 devstate_sched_start = 1; 00854 } 00855 00856 ast_mutex_lock(&refreshlock); 00857 AST_SCHED_REPLACE(old_event->bs_start_sched, sched, devstate_sched_start, calendar_devstate_change, old_event); 00858 ast_mutex_unlock(&refreshlock); 00859 ast_debug(3, "Calendar bs_start event notification scheduled to happen in %ld ms\n", (long) devstate_sched_start); 00860 } 00861 00862 if (!cmp_event || old_event->end != event->end) { 00863 changed = 1; 00864 devstate_sched_end = (event->end - now.tv_sec) * 1000; 00865 ast_mutex_lock(&refreshlock); 00866 AST_SCHED_REPLACE(old_event->bs_end_sched, sched, devstate_sched_end, calendar_devstate_change, old_event); 00867 ast_mutex_unlock(&refreshlock); 00868 ast_debug(3, "Calendar bs_end event notification scheduled to happen in %ld ms\n", (long) devstate_sched_end); 00869 } 00870 00871 if (changed) { 00872 ast_cond_signal(&refresh_condition); 00873 } 00874 00875 ao2_unlock(event); 00876 00877 return 0; 00878 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1658 of file res_calendar.c.
References ao2_callback, ARRAY_LEN, ast_cli_unregister_multiple(), 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_unload_resource(), calendar_busy_function, calendar_cli, 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, and OBJ_UNLINK.
01659 { 01660 struct ast_calendar_tech *tech; 01661 01662 ast_devstate_prov_del("calendar"); 01663 ast_custom_function_unregister(&calendar_busy_function); 01664 ast_custom_function_unregister(&calendar_event_function); 01665 ast_custom_function_unregister(&calendar_query_function); 01666 ast_custom_function_unregister(&calendar_query_result_function); 01667 ast_custom_function_unregister(&calendar_write_function); 01668 ast_cli_unregister_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01669 01670 /* Remove all calendars */ 01671 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); 01672 01673 AST_LIST_LOCK(&techs); 01674 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, tech, list) { 01675 ast_unload_resource(tech->module, 0); 01676 } 01677 AST_LIST_TRAVERSE_SAFE_END; 01678 AST_LIST_UNLOCK(&techs); 01679 01680 return 0; 01681 }
static struct ast_calendar* unref_calendar | ( | struct ast_calendar * | cal | ) | [static] |
Definition at line 219 of file res_calendar.c.
References ao2_ref.
Referenced by build_calendar(), calendar_query_exec(), handle_show_calendar(), handle_show_calendars(), and load_tech_calendars().
00220 { 00221 ao2_ref(cal, -1); 00222 return NULL; 00223 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static] |
Definition at line 1727 of file res_calendar.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1727 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 977 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 1527 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ast_config* calendar_config [static] |
Definition at line 199 of file res_calendar.c.
Referenced by load_config(), and load_tech_calendars().
struct ast_custom_function calendar_event_function [static] |
Initial value:
{ .name = "CALENDAR_EVENT", .read = calendar_event_read, }
Definition at line 1586 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 1157 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 1268 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 1375 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ao2_container* calendars [static] |
ast_rwlock_t config_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER } [static] |
Definition at line 200 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 179 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 185 of file res_calendar.c.
Referenced by calendar_query_exec(), and calendar_query_result_exec().
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 629 of file res_calendar.c.
ast_cond_t refresh_condition [static] |
Definition at line 171 of file res_calendar.c.
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
Definition at line 169 of file res_calendar.c.
ast_mutex_t refreshlock [static] |
Definition at line 170 of file res_calendar.c.
Referenced by caldav_load_calendar(), do_refresh(), ewscal_load_calendar(), exchangecal_load_calendar(), ical_load_calendar(), load_module(), and schedule_calendar_event().
ast_mutex_t reloadlock [static] |
Definition at line 172 of file res_calendar.c.
struct sched_context* sched [static] |
Definition at line 168 of file res_calendar.c.