#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 (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_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 = "ac1f6a56484a8820659555499174e588" , .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 = { 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_context * | sched |
Support writing attendees
Definition in file res_calendar.c.
#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" |
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.
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).
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.
cal | calendar to allocate an event for |
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.
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().
00626 { 00627 return ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn); 00628 }
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 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.
tech | calendar technology to register |
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.
event | event to unref |
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.
tech | calendar technology to unregister |
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(¬ify_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] |
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] |
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] |
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.
01712 { 01713 struct ast_calendar_tech *tech; 01714 01715 ast_devstate_prov_del("calendar"); 01716 ast_custom_function_unregister(&calendar_busy_function); 01717 ast_custom_function_unregister(&calendar_event_function); 01718 ast_custom_function_unregister(&calendar_query_function); 01719 ast_custom_function_unregister(&calendar_query_result_function); 01720 ast_custom_function_unregister(&calendar_write_function); 01721 ast_cli_unregister_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01722 01723 /* Remove all calendars */ 01724 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); 01725 01726 ast_mutex_lock(&refreshlock); 01727 module_unloading = 1; 01728 ast_cond_signal(&refresh_condition); 01729 ast_mutex_unlock(&refreshlock); 01730 pthread_join(refresh_thread, NULL); 01731 01732 AST_LIST_LOCK(&techs); 01733 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, tech, list) { 01734 ast_unload_resource(tech->module, 0); 01735 } 01736 AST_LIST_TRAVERSE_SAFE_END; 01737 AST_LIST_UNLOCK(&techs); 01738 01739 ast_config_destroy(calendar_config); 01740 calendar_config = NULL; 01741 01742 return 0; 01743 }
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 }
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] |
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.