#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. | |
| struct 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. | |
| struct ast_calendar_event * | ast_calendar_event_alloc (struct ast_calendar *cal) |
| Allocate an astobj2 ast_calendar_event object. | |
| struct 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. | |
| struct 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 , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| 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 = { 0 } |
| 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 |
Definition in file res_calendar.c.
| #define CALENDAR_BUCKETS 19 |
Definition at line 159 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 1691 of file res_calendar.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1691 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 970 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, evententry::list, LOG_ERROR, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.
Referenced by calendar_query_exec().
00971 { 00972 struct evententry *entry, *iter; 00973 int event_startdiff = abs(start - event->start); 00974 int event_enddiff = abs(end - event->end); 00975 int i = 0; 00976 00977 if (!(entry = ast_calloc(1, sizeof(*entry)))) { 00978 ast_log(LOG_ERROR, "Unable to allocate memory for event list\n"); 00979 return -1; 00980 } 00981 00982 entry->event = event; 00983 ao2_ref(event, +1); 00984 00985 if (start == end) { 00986 AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) { 00987 int startdiff = abs(iter->event->start - start); 00988 00989 ast_debug(10, "Comparing %s with startdiff %d to %s with startdiff %d\n", event->summary, event_startdiff, iter->event->summary, startdiff); 00990 ++i; 00991 if (startdiff > event_startdiff) { 00992 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 00993 return i; 00994 } 00995 if (startdiff == event_startdiff) { 00996 int enddiff = abs(iter->event->end - end); 00997 00998 if (enddiff > event_enddiff) { 00999 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01000 return i; 01001 } 01002 if (event_startdiff == enddiff) { 01003 if (strcmp(event->uid, iter->event->uid) < 0) { 01004 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01005 return i; 01006 } 01007 } 01008 } 01009 } 01010 AST_LIST_TRAVERSE_SAFE_END; 01011 01012 AST_LIST_INSERT_TAIL(events, entry, list); 01013 01014 return i; 01015 } 01016 01017 AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) { 01018 ++i; 01019 if (iter->event->start > event->start) { 01020 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01021 return i; 01022 } 01023 01024 if (iter->event->start == event->start) { 01025 if ((iter->event->end - iter->event->start) == (event->end - event->start)) { 01026 if (strcmp(event->uid, iter->event->uid) < 0) { 01027 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01028 return i; 01029 } 01030 } 01031 if ((iter->event->end - iter->event->start) < (event->end - event->start)) { 01032 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01033 return i; 01034 } 01035 } 01036 } 01037 AST_LIST_TRAVERSE_SAFE_END; 01038 01039 AST_LIST_INSERT_TAIL(events, entry, list); 01040 01041 return i; 01042 }
| static int add_new_event_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 895 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().
00896 { 00897 struct ast_calendar_event *new_event = obj; 00898 struct ao2_container *events = arg; 00899 00900 ao2_link(events, new_event); 00901 schedule_calendar_event(new_event->owner, new_event, NULL); 00902 return CMP_MATCH; 00903 }
| 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 545 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().
00546 { 00547 ast_debug(3, "Clearing all events for calendar %s\n", cal->name); 00548 00549 ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, clear_events_cb, NULL); 00550 }
| struct ast_config* ast_calendar_config_acquire | ( | void | ) | [read] |
Grab and lock pointer to the calendar config (read only).
Definition at line 196 of file res_calendar.c.
References ast_rwlock_rdlock(), and ast_rwlock_unlock().
Referenced by caldav_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().
00197 { 00198 ast_rwlock_rdlock(&config_lock); 00199 00200 if (!calendar_config) { 00201 ast_rwlock_unlock(&config_lock); 00202 return NULL; 00203 } 00204 00205 return calendar_config; 00206 }
| void ast_calendar_config_release | ( | void | ) |
Release the calendar config.
Definition at line 208 of file res_calendar.c.
References ast_rwlock_unlock(), and config_lock.
Referenced by caldav_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().
00209 { 00210 ast_rwlock_unlock(&config_lock); 00211 }
| struct ast_calendar_event* ast_calendar_event_alloc | ( | struct ast_calendar * | cal | ) | [read] |
Allocate an astobj2 ast_calendar_event object.
| cal | calendar to allocate an event for |
Definition at line 552 of file res_calendar.c.
References ao2_alloc, ast_calendar_unref_event(), AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, ast_calendar_event::attendees, calendar_event_destructor(), and evententry::event.
Referenced by caldav_add_event(), calendar_write_exec(), icalendar_add_event(), and parse_tag().
00553 { 00554 struct ast_calendar_event *event; 00555 if (!(event = ao2_alloc(sizeof(*event), calendar_event_destructor))) { 00556 return NULL; 00557 } 00558 00559 if (ast_string_field_init(event, 32)) { 00560 event = ast_calendar_unref_event(event); 00561 return NULL; 00562 } 00563 00564 event->owner = cal; 00565 event->notify_sched = -1; 00566 event->bs_start_sched = -1; 00567 event->bs_end_sched = -1; 00568 00569 AST_LIST_HEAD_INIT_NOLOCK(&event->attendees); 00570 00571 return event; 00572 }
| struct ao2_container* ast_calendar_event_container_alloc | ( | void | ) | [read] |
Allocate an astobj2 container for ast_calendar_event objects.
Definition at line 574 of file res_calendar.c.
References ao2_container_alloc, CALENDAR_BUCKETS, event_cmp_fn(), and event_hash_fn().
Referenced by caldav_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().
00575 { 00576 return ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn); 00577 }
| 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 905 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 icalendar_update_events(), update_caldav(), and update_exchangecal().
00906 { 00907 /* Loop through all events attached to the calendar. If there is a matching new event 00908 * merge its data over and handle any schedule changes that need to be made. Then remove 00909 * the new_event from new_events so that we are left with only new_events that we can add later. */ 00910 ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, merge_events_cb, new_events); 00911 00912 /* Now, we should only have completely new events in new_events. Loop through and add them */ 00913 ao2_callback(new_events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, add_new_event_cb, cal->events); 00914 }
| 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 441 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, evententry::list, load_tech_calendars(), LOG_WARNING, and ast_calendar_tech::type.
Referenced by load_module().
00442 { 00443 struct ast_calendar_tech *iter; 00444 00445 AST_LIST_LOCK(&techs); 00446 AST_LIST_TRAVERSE(&techs, iter, list) { 00447 if(!strcasecmp(tech->type, iter->type)) { 00448 ast_log(LOG_WARNING, "Already have a handler for calendar type '%s'\n", tech->type); 00449 AST_LIST_UNLOCK(&techs); 00450 return -1; 00451 } 00452 } 00453 AST_LIST_INSERT_HEAD(&techs, tech, list); 00454 AST_LIST_UNLOCK(&techs); 00455 00456 ast_verb(2, "Registered calendar type '%s' (%s)\n", tech->type, tech->description); 00457 00458 return load_tech_calendars(tech); 00459 }
| struct ast_calendar_event* ast_calendar_unref_event | ( | struct ast_calendar_event * | event | ) | [read] |
Unreference an ast_calendar_event.
| event | event to unref |
Definition at line 259 of file res_calendar.c.
References ao2_ref.
Referenced by ast_calendar_event_alloc(), caldav_add_event(), calendar_devstate_change(), calendar_query_exec(), calendar_write_exec(), do_notify(), event_notification_destroy(), handle_show_calendar(), icalendar_add_event(), merge_events_cb(), and parse_tag().
00260 { 00261 ao2_ref(event, -1); 00262 return NULL; 00263 }
| 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 473 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, evententry::list, match_caltech_cb(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and ast_calendar_tech::type.
Referenced by load_tech_calendars(), and unload_module().
00474 { 00475 struct ast_calendar_tech *iter; 00476 00477 AST_LIST_LOCK(&techs); 00478 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, iter, list) { 00479 if (iter != tech) { 00480 continue; 00481 } 00482 00483 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, match_caltech_cb, tech); 00484 00485 AST_LIST_REMOVE_CURRENT(list); 00486 ast_verb(2, "Unregistered calendar type '%s'\n", tech->type); 00487 break; 00488 } 00489 AST_LIST_TRAVERSE_SAFE_END; 00490 AST_LIST_UNLOCK(&techs); 00491 00492 }
| static struct ast_calendar* build_calendar | ( | struct ast_config * | cfg, | |
| const char * | cat, | |||
| const struct ast_calendar_tech * | tech | |||
| ) | [static, read] |
Definition at line 333 of file res_calendar.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_unlink, ast_cond_init(), ast_log(), ast_pthread_create, AST_PTHREADT_NULL, ast_string_field_init, ast_string_field_set, ast_variable_browse(), ast_calendar::autoreminder, CALENDAR_BUCKETS, calendar_destructor(), event_cmp_fn(), event_hash_fn(), ast_calendar::events, find_calendar(), ast_calendar_tech::load_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::thread, ast_calendar::timeframe, ast_calendar::unload, unref_calendar(), and ast_variable::value.
Referenced by load_tech_calendars().
00334 { 00335 struct ast_calendar *cal; 00336 struct ast_variable *v; 00337 int new_calendar = 0; 00338 00339 if (!(cal = find_calendar(cat))) { 00340 new_calendar = 1; 00341 if (!(cal = ao2_alloc(sizeof(*cal), calendar_destructor))) { 00342 ast_log(LOG_ERROR, "Could not allocate calendar structure. Stopping.\n"); 00343 return NULL; 00344 } 00345 00346 if (!(cal->events = ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn))) { 00347 ast_log(LOG_ERROR, "Could not allocate events container for %s\n", cat); 00348 cal = unref_calendar(cal); 00349 return NULL; 00350 } 00351 00352 if (ast_string_field_init(cal, 32)) { 00353 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", cat); 00354 cal = unref_calendar(cal); 00355 return NULL; 00356 } 00357 } else { 00358 cal->pending_deletion = 0; 00359 } 00360 00361 ast_string_field_set(cal, name, cat); 00362 cal->tech = tech; 00363 00364 cal->refresh = 3600; 00365 cal->timeframe = 60; 00366 00367 for (v = ast_variable_browse(cfg, cat); v; v = v->next) { 00368 if (!strcasecmp(v->name, "autoreminder")) { 00369 cal->autoreminder = atoi(v->value); 00370 } else if (!strcasecmp(v->name, "channel")) { 00371 ast_string_field_set(cal, notify_channel, v->value); 00372 } else if (!strcasecmp(v->name, "context")) { 00373 ast_string_field_set(cal, notify_context, v->value); 00374 } else if (!strcasecmp(v->name, "extension")) { 00375 ast_string_field_set(cal, notify_extension, v->value); 00376 } else if (!strcasecmp(v->name, "waittime")) { 00377 cal->notify_waittime = atoi(v->value); 00378 } else if (!strcasecmp(v->name, "app")) { 00379 ast_string_field_set(cal, notify_app, v->value); 00380 } else if (!strcasecmp(v->name, "appdata")) { 00381 ast_string_field_set(cal, notify_appdata, v->value); 00382 } else if (!strcasecmp(v->name, "refresh")) { 00383 cal->refresh = atoi(v->value); 00384 } else if (!strcasecmp(v->name, "timeframe")) { 00385 cal->timeframe = atoi(v->value); 00386 } 00387 } 00388 00389 if (new_calendar) { 00390 cal->thread = AST_PTHREADT_NULL; 00391 ast_cond_init(&cal->unload, NULL); 00392 ao2_link(calendars, cal); 00393 if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) { 00394 /* If we start failing to create threads, go ahead and return NULL 00395 * and the tech module will be unregistered 00396 */ 00397 ao2_unlink(calendars, cal); 00398 cal = unref_calendar(cal); 00399 } 00400 } 00401 00402 return cal; 00403 }
| static int calendar_busy_callback | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 295 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().
00296 { 00297 struct ast_calendar_event *event = obj; 00298 int *is_busy = arg; 00299 struct timeval tv = ast_tvnow(); 00300 00301 if (tv.tv_sec >= event->start && tv.tv_sec <= event->end && event->busy_state > AST_CALENDAR_BS_FREE) { 00302 *is_busy = 1; 00303 return CMP_STOP; 00304 } 00305 00306 return 0; 00307 }
| 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 944 of file res_calendar.c.
References ast_log(), ast_strlen_zero(), calendar_is_busy(), find_calendar(), and LOG_WARNING.
00945 { 00946 struct ast_calendar *cal; 00947 00948 if (ast_strlen_zero(data)) { 00949 ast_log(LOG_WARNING, "CALENDAR_BUSY requires an argument: CALENDAR_BUSY(<calendar_name>)\n"); 00950 return -1; 00951 } 00952 00953 cal = find_calendar(data); 00954 00955 if (!cal) { 00956 ast_log(LOG_WARNING, "Could not find calendar '%s'\n", data); 00957 return -1; 00958 } 00959 00960 strcpy(buf, calendar_is_busy(cal) ? "1" : "0"); 00961 00962 return 0; 00963 }
| static int calendar_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 225 of file res_calendar.c.
References CMP_MATCH, CMP_STOP, and ast_calendar::name.
Referenced by load_module().
00226 { 00227 const struct ast_calendar *one = obj, *two = arg; 00228 return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP: 0; 00229 }
| static void calendar_destructor | ( | void * | obj | ) | [static] |
Definition at line 265 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().
00266 { 00267 struct ast_calendar *cal = obj; 00268 00269 ast_debug(3, "Destroying calendar %s\n", cal->name); 00270 00271 ao2_lock(cal); 00272 cal->unloading = 1; 00273 ast_cond_signal(&cal->unload); 00274 pthread_join(cal->thread, NULL); 00275 if (cal->tech_pvt) { 00276 cal->tech_pvt = cal->tech->unref_calendar(cal->tech_pvt); 00277 } 00278 ast_calendar_clear_events(cal); 00279 ast_string_field_free_memory(cal); 00280 ao2_ref(cal->events, -1); 00281 ao2_unlock(cal); 00282 }
| static int calendar_devstate_change | ( | const void * | data | ) | [static] |
Definition at line 746 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(), calendar_is_busy(), evententry::event, LOG_WARNING, ast_calendar::name, and ast_calendar_event::owner.
Referenced by schedule_calendar_event().
00747 { 00748 struct ast_calendar_event *event = (struct ast_calendar_event *)data; 00749 struct timeval now = ast_tvnow(); 00750 int is_end_event; 00751 00752 if (!event) { 00753 ast_log(LOG_WARNING, "Event was NULL!\n"); 00754 return 0; 00755 } 00756 00757 ao2_ref(event, +1); 00758 00759 is_end_event = event->end <= now.tv_sec; 00760 00761 if (is_end_event) { 00762 event->bs_end_sched = -1; 00763 } else { 00764 event->bs_start_sched = -1; 00765 } 00766 00767 /* We can have overlapping events, so ignore the event->busy_state and check busy state 00768 * based on all events in the calendar */ 00769 if (!calendar_is_busy(event->owner)) { 00770 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); 00771 } else { 00772 ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); 00773 } 00774 00775 event = ast_calendar_unref_event(event); 00776 00777 return 0; 00778 }
| static void calendar_event_destructor | ( | void * | obj | ) | [static] |
Definition at line 494 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, evententry::event, ast_calendar::name, evententry::next, and ast_calendar_event::owner.
Referenced by ast_calendar_event_alloc().
00495 { 00496 struct ast_calendar_event *event = obj; 00497 struct ast_calendar_attendee *attendee; 00498 00499 ast_debug(3, "Destroying event for calendar '%s'\n", event->owner->name); 00500 ast_string_field_free_memory(event); 00501 while ((attendee = AST_LIST_REMOVE_HEAD(&event->attendees, next))) { 00502 if (attendee->data) { 00503 ast_free(attendee->data); 00504 } 00505 ast_free(attendee); 00506 } 00507 }
| static int calendar_event_notify | ( | const void * | data | ) | [static] |
Definition at line 722 of file res_calendar.c.
References ao2_ref, ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, do_notify(), evententry::event, LOG_ERROR, and ast_calendar_event::owner.
Referenced by schedule_calendar_event().
00723 { 00724 struct ast_calendar_event *event = (void *)data; 00725 int res = -1; 00726 pthread_t notify_thread = AST_PTHREADT_NULL; 00727 00728 if (!(event && event->owner)) { 00729 ast_log(LOG_ERROR, "Extremely low-cal...in fact cal is NULL!\n"); 00730 return res; 00731 } 00732 00733 ao2_ref(event, +1); 00734 event->notify_sched = -1; 00735 00736 if (ast_pthread_create_background(¬ify_thread, NULL, do_notify, event) < 0) { 00737 ast_log(LOG_ERROR, "Could not create notification thread\n"); 00738 return res; 00739 } 00740 00741 res = 0; 00742 00743 return res; 00744 }
| static int calendar_event_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1502 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_datastore::data, ast_calendar_event::description, ast_calendar_event::end, evententry::event, ast_calendar_event::location, LOG_WARNING, ast_calendar::name, ast_channel::name, ast_calendar_event::organizer, ast_calendar_event::owner, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.
01503 { 01504 struct ast_datastore *datastore; 01505 struct ast_calendar_event *event; 01506 01507 if (ast_strlen_zero(data)) { 01508 ast_log(LOG_WARNING, "%s requires an argument\n", cmd); 01509 return -1; 01510 } 01511 01512 ast_channel_lock(chan); 01513 if (!(datastore = ast_channel_datastore_find(chan, &event_notification_datastore, NULL))) { 01514 ast_log(LOG_WARNING, "There is no event notification datastore on '%s'!\n", chan->name); 01515 ast_channel_unlock(chan); 01516 return -1; 01517 } 01518 ast_channel_unlock(chan); 01519 01520 if (!(event = datastore->data)) { 01521 ast_log(LOG_WARNING, "The datastore contains no data!\n"); 01522 return -1; 01523 } 01524 01525 if (!strcasecmp(data, "summary")) { 01526 ast_copy_string(buf, event->summary, len); 01527 } else if (!strcasecmp(data, "description")) { 01528 ast_copy_string(buf, event->description, len); 01529 } else if (!strcasecmp(data, "organizer")) { 01530 ast_copy_string(buf, event->organizer, len); 01531 } else if (!strcasecmp(data, "location")) { 01532 ast_copy_string(buf, event->location, len); 01533 } else if (!strcasecmp(data, "calendar")) { 01534 ast_copy_string(buf, event->owner->name, len); 01535 } else if (!strcasecmp(data, "uid")) { 01536 ast_copy_string(buf, event->uid, len); 01537 } else if (!strcasecmp(data, "start")) { 01538 snprintf(buf, len, "%ld", (long)event->start); 01539 } else if (!strcasecmp(data, "end")) { 01540 snprintf(buf, len, "%ld", (long)event->end); 01541 } else if (!strcasecmp(data, "busystate")) { 01542 snprintf(buf, len, "%d", event->busy_state); 01543 } else if (!strcasecmp(data, "attendees")) { 01544 calendar_join_attendees(event, buf, len); 01545 } 01546 01547 01548 return 0; 01549 }
| static int calendar_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 219 of file res_calendar.c.
References ast_str_case_hash(), and ast_calendar::name.
Referenced by load_module().
00220 { 00221 const struct ast_calendar *cal = obj; 00222 return ast_str_case_hash(cal->name); 00223 }
| static int calendar_is_busy | ( | struct ast_calendar * | cal | ) | [static] |
Definition at line 309 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().
00310 { 00311 int is_busy = 0; 00312 00313 ao2_callback(cal->events, OBJ_NODATA, calendar_busy_callback, &is_busy); 00314 00315 return is_busy; 00316 }
| static void calendar_join_attendees | ( | struct ast_calendar_event * | event, | |
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1150 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 evententry::next.
Referenced by calendar_event_read(), and calendar_query_result_exec().
01151 { 01152 struct ast_str *tmp; 01153 struct ast_calendar_attendee *attendee; 01154 01155 if (!(tmp = ast_str_create(32))) { 01156 ast_log(LOG_ERROR, "Could not allocate memory for attendees!\n"); 01157 return; 01158 } 01159 01160 AST_LIST_TRAVERSE(&event->attendees, attendee, next) { 01161 ast_str_append(&tmp, 0, "%s%s", attendee == AST_LIST_FIRST(&event->attendees) ? "" : ",", attendee->data); 01162 } 01163 01164 ast_copy_string(buf, ast_str_buffer(tmp), len); 01165 ast_free(tmp); 01166 }
| static int calendar_query_exec | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1064 of file res_calendar.c.
References add_event_to_list(), ao2_alloc, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, 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, evententry::event, 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().
01065 { 01066 struct ast_calendar *cal; 01067 struct ao2_iterator i; 01068 struct ast_calendar_event *event; 01069 struct eventlist *events; 01070 time_t start = INT_MIN, end = INT_MAX; 01071 struct ast_datastore *eventlist_datastore; 01072 AST_DECLARE_APP_ARGS(args, 01073 AST_APP_ARG(calendar); 01074 AST_APP_ARG(start); 01075 AST_APP_ARG(end); 01076 ); 01077 01078 if (!chan) { 01079 ast_log(LOG_WARNING, "%s requires a channel to store the data on\n", cmd); 01080 return -1; 01081 } 01082 01083 AST_STANDARD_APP_ARGS(args, data); 01084 01085 if (ast_strlen_zero(args.calendar)) { 01086 ast_log(LOG_WARNING, "%s requires a calendar argument\n", cmd); 01087 return -1; 01088 } 01089 01090 if (!(cal = find_calendar(args.calendar))) { 01091 ast_log(LOG_WARNING, "Unknown calendar '%s'\n", args.calendar); 01092 return -1; 01093 } 01094 01095 if (!(events = ao2_alloc(sizeof(*events), eventlist_destructor))) { 01096 ast_log(LOG_ERROR, "Unable to allocate memory for event list\n"); 01097 cal = unref_calendar(cal); 01098 return -1; 01099 } 01100 01101 if (!ast_strlen_zero(args.start)) { 01102 start = atoi(args.start); 01103 } 01104 01105 if (!ast_strlen_zero(args.end)) { 01106 end = atoi(args.end); 01107 } 01108 01109 i = ao2_iterator_init(cal->events, 0); 01110 while ((event = ao2_iterator_next(&i))) { 01111 if (!(start > event->end || end < event->start)) { 01112 ast_debug(10, "%s (%ld - %ld) overlapped with (%ld - %ld)\n", event->summary, (long) event->start, (long) event->end, (long) start, (long) end); 01113 if (add_event_to_list(events, event, start, end) < 0) { 01114 event = ast_calendar_unref_event(event); 01115 ao2_iterator_destroy(&i); 01116 return -1; 01117 } 01118 } 01119 01120 event = ast_calendar_unref_event(event); 01121 } 01122 ao2_iterator_destroy(&i); 01123 01124 ast_channel_lock(chan); 01125 do { 01126 generate_random_string(buf, len); 01127 } while (ast_channel_datastore_find(chan, &eventlist_datastore_info, buf)); 01128 ast_channel_unlock(chan); 01129 01130 if (!(eventlist_datastore = ast_datastore_alloc(&eventlist_datastore_info, buf))) { 01131 ast_log(LOG_ERROR, "Could not allocate datastore!\n"); 01132 return -1; 01133 } 01134 01135 eventlist_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01136 eventlist_datastore->data = events; 01137 01138 ast_channel_lock(chan); 01139 ast_channel_datastore_add(chan, eventlist_datastore); 01140 ast_channel_unlock(chan); 01141 01142 return 0; 01143 }
| static int calendar_query_result_exec | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1168 of file res_calendar.c.
References 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_datastore::data, ast_calendar_event::description, ast_calendar_event::end, evententry::event, 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::start, ast_calendar_event::summary, and ast_calendar_event::uid.
01169 { 01170 struct ast_datastore *datastore; 01171 struct eventlist *events; 01172 struct evententry *entry; 01173 int row = 1; 01174 size_t listlen = 0; 01175 AST_DECLARE_APP_ARGS(args, 01176 AST_APP_ARG(id); 01177 AST_APP_ARG(field); 01178 AST_APP_ARG(row); 01179 ); 01180 01181 if (!chan) { 01182 ast_log(LOG_WARNING, "%s requires a channel\n", cmd); 01183 return -1; 01184 } 01185 01186 AST_STANDARD_APP_ARGS(args, data); 01187 01188 if (ast_strlen_zero(args.id) || ast_strlen_zero(args.field)) { 01189 ast_log(LOG_WARNING, "%s requires an id and a field", cmd); 01190 return -1; 01191 } 01192 01193 ast_channel_lock(chan); 01194 if (!(datastore = ast_channel_datastore_find(chan, &eventlist_datastore_info, args.id))) { 01195 ast_log(LOG_WARNING, "There is no event notification datastore with id '%s' on '%s'!\n", args.id, chan->name); 01196 ast_channel_unlock(chan); 01197 return -1; 01198 } 01199 ast_channel_unlock(chan); 01200 01201 if (!(events = datastore->data)) { 01202 ast_log(LOG_WARNING, "The datastore contains no data!\n"); 01203 return -1; 01204 } 01205 01206 if (!ast_strlen_zero(args.row)) { 01207 row = atoi(args.row); 01208 } 01209 01210 AST_LIST_TRAVERSE(events, entry, list) { 01211 listlen++; 01212 } 01213 01214 if (!strcasecmp(args.field, "getnum")) { 01215 snprintf(buf, len, "%zu", listlen); 01216 return 0; 01217 } 01218 01219 AST_LIST_TRAVERSE(events, entry, list) { 01220 if (--row) { 01221 continue; 01222 } 01223 if (!strcasecmp(args.field, "summary")) { 01224 ast_copy_string(buf, entry->event->summary, len); 01225 } else if (!strcasecmp(args.field, "description")) { 01226 ast_copy_string(buf, entry->event->description, len); 01227 } else if (!strcasecmp(args.field, "organizer")) { 01228 ast_copy_string(buf, entry->event->organizer, len); 01229 } else if (!strcasecmp(args.field, "location")) { 01230 ast_copy_string(buf, entry->event->location, len); 01231 } else if (!strcasecmp(args.field, "calendar")) { 01232 ast_copy_string(buf, entry->event->owner->name, len); 01233 } else if (!strcasecmp(args.field, "uid")) { 01234 ast_copy_string(buf, entry->event->uid, len); 01235 } else if (!strcasecmp(args.field, "start")) { 01236 snprintf(buf, len, "%ld", (long) entry->event->start); 01237 } else if (!strcasecmp(args.field, "end")) { 01238 snprintf(buf, len, "%ld", (long) entry->event->end); 01239 } else if (!strcasecmp(args.field, "busystate")) { 01240 snprintf(buf, len, "%d", entry->event->busy_state); 01241 } else if (!strcasecmp(args.field, "attendees")) { 01242 calendar_join_attendees(entry->event, buf, len); 01243 } else { 01244 ast_log(LOG_WARNING, "Unknown field '%s'\n", args.field); 01245 } 01246 break; 01247 } 01248 01249 return 0; 01250 }
| static int calendar_write_exec | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 1257 of file res_calendar.c.
References AST_APP_ARG, ast_calendar_event_alloc(), ast_calendar_unref_event(), AST_DECLARE_APP_ARGS, ast_free, ast_log(), AST_STANDARD_APP_ARGS, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_calendar_event::description, evententry::event, find_calendar(), ast_calendar_event::location, LOG_ERROR, LOG_WARNING, ast_calendar::name, ast_calendar_event::organizer, ast_calendar_event::summary, ast_calendar::tech, ast_calendar_event::uid, unref_calendar(), and ast_calendar_tech::write_event.
01258 { 01259 int i, j, ret = -1; 01260 char *val_dup = NULL; 01261 struct ast_calendar *cal = NULL; 01262 struct ast_calendar_event *event = NULL; 01263 AST_DECLARE_APP_ARGS(fields, 01264 AST_APP_ARG(field)[10]; 01265 ); 01266 AST_DECLARE_APP_ARGS(values, 01267 AST_APP_ARG(value)[10]; 01268 ); 01269 01270 if (!(val_dup = ast_strdup(value))) { 01271 ast_log(LOG_ERROR, "Could not allocate memory for values\n"); 01272 return -1; 01273 } 01274 01275 AST_STANDARD_APP_ARGS(fields, data); 01276 AST_STANDARD_APP_ARGS(values, val_dup); 01277 01278 /* XXX Eventually we will support unnamed calendars, so if we don't find one, we parse 01279 * for a calendar type and create it */ 01280 if (!(cal = find_calendar(fields.field[0]))) { 01281 ast_log(LOG_WARNING, "Couldn't find calendar '%s'\n", fields.field[0]); 01282 goto write_cleanup; 01283 } 01284 01285 if (!(cal->tech->write_event)) { 01286 ast_log(LOG_WARNING, "Calendar '%s' has no write function!\n", cal->name); 01287 goto write_cleanup; 01288 } 01289 01290 if (!(event = ast_calendar_event_alloc(cal))) { 01291 goto write_cleanup; 01292 } 01293 01294 if (ast_strlen_zero(fields.field[0])) { 01295 ast_log(LOG_WARNING, "CALENDAR_WRITE requires a calendar name!\n"); 01296 goto write_cleanup; 01297 } 01298 01299 if (fields.argc - 1 != values.argc) { 01300 ast_log(LOG_WARNING, "CALENDAR_WRITE should have the same number of fields (%d) and values (%d)!\n", fields.argc - 1, values.argc); 01301 goto write_cleanup; 01302 } 01303 01304 event->owner = cal; 01305 01306 for (i = 1, j = 0; i < fields.argc; i++, j++) { 01307 if (!strcasecmp(fields.field[i], "summary")) { 01308 ast_string_field_set(event, summary, values.value[j]); 01309 } else if (!strcasecmp(fields.field[i], "description")) { 01310 ast_string_field_set(event, description, values.value[j]); 01311 } else if (!strcasecmp(fields.field[i], "organizer")) { 01312 ast_string_field_set(event, organizer, values.value[j]); 01313 } else if (!strcasecmp(fields.field[i], "location")) { 01314 ast_string_field_set(event, location, values.value[j]); 01315 } else if (!strcasecmp(fields.field[i], "uid")) { 01316 ast_string_field_set(event, uid, values.value[j]); 01317 } else if (!strcasecmp(fields.field[i], "start")) { 01318 event->start = atoi(values.value[j]); 01319 } else if (!strcasecmp(fields.field[i], "end")) { 01320 event->end = atoi(values.value[j]); 01321 } else if (!strcasecmp(fields.field[i], "busystate")) { 01322 event->busy_state = atoi(values.value[j]); 01323 } else { 01324 ast_log(LOG_WARNING, "Unknown calendar event field '%s'\n", fields.field[i]); 01325 } 01326 } 01327 01328 if((ret = cal->tech->write_event(event))) { 01329 ast_log(LOG_WARNING, "Writing event to calendar '%s' failed!\n", cal->name); 01330 } 01331 01332 write_cleanup: 01333 if (cal) { 01334 cal = unref_calendar(cal); 01335 } 01336 if (event) { 01337 event = ast_calendar_unref_event(event); 01338 } 01339 if (val_dup) { 01340 ast_free(val_dup); 01341 } 01342 01343 return ret; 01344 }
| static enum ast_device_state calendarstate | ( | const char * | data | ) | [static] |
Definition at line 318 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().
00319 { 00320 struct ast_calendar *cal; 00321 00322 if (ast_strlen_zero(data) || (!(cal = find_calendar(data)))) { 00323 return AST_DEVICE_INVALID; 00324 } 00325 00326 if (cal->tech->is_busy) { 00327 return cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; 00328 } 00329 00330 return calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; 00331 }
| static int cb_pending_deletion | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1556 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::pending_deletion.
Referenced by reload().
01557 { 01558 struct ast_calendar *cal = user_data; 01559 01560 cal->pending_deletion = 1; 01561 01562 return CMP_MATCH; 01563 }
| static int cb_rm_pending_deletion | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1565 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::pending_deletion.
Referenced by reload().
01566 { 01567 struct ast_calendar *cal = user_data; 01568 01569 return cal->pending_deletion ? CMP_MATCH : 0; 01570 }
| static int clear_events_cb | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 536 of file res_calendar.c.
References CMP_MATCH, destroy_event(), and evententry::event.
Referenced by ast_calendar_clear_events().
00537 { 00538 struct ast_calendar_event *event = user_data; 00539 00540 event = destroy_event(event); 00541 00542 return CMP_MATCH; 00543 }
| static void copy_event_data | ( | struct ast_calendar_event * | dst, | |
| struct ast_calendar_event * | src | |||
| ) | [static] |
Definition at line 780 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::description, ast_calendar_event::end, ast_calendar_event::location, evententry::next, ast_calendar_event::organizer, ast_calendar_event::owner, ast_calendar_event::start, ast_calendar_event::summary, and ast_calendar_event::uid.
Referenced by merge_events_cb().
00781 { 00782 struct ast_calendar_attendee *attendee; 00783 00784 ast_string_field_set(dst, summary, src->summary); 00785 ast_string_field_set(dst, description, src->description); 00786 ast_string_field_set(dst, organizer, src->organizer); 00787 ast_string_field_set(dst, location, src->location); 00788 ast_string_field_set(dst, uid, src->uid); 00789 dst->owner = src->owner; 00790 dst->start = src->start; 00791 dst->end = src->end; 00792 dst->alarm = src->alarm; 00793 dst->busy_state = src->busy_state; 00794 00795 /* Delete any existing attendees */ 00796 while ((attendee = AST_LIST_REMOVE_HEAD(&dst->attendees, next))) { 00797 ast_free(attendee); 00798 } 00799 00800 /* Copy over the new attendees */ 00801 while ((attendee = AST_LIST_REMOVE_HEAD(&src->attendees, next))) { 00802 AST_LIST_INSERT_TAIL(&dst->attendees, attendee, next); 00803 } 00804 }
| static struct ast_calendar_event* destroy_event | ( | struct ast_calendar_event * | event | ) | [static, read] |
Definition at line 511 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, and ast_calendar_event::owner.
Referenced by clear_events_cb(), and merge_events_cb().
00512 { 00513 if (event->notify_sched > -1 && ast_sched_del(sched, event->notify_sched)) { 00514 ast_debug(3, "Notification running, can't delete sched entry\n"); 00515 } 00516 if (event->bs_start_sched > -1 && ast_sched_del(sched, event->bs_start_sched)) { 00517 ast_debug(3, "Devicestate update (start) running, can't delete sched entry\n"); 00518 } 00519 if (event->bs_end_sched > -1 && ast_sched_del(sched, event->bs_end_sched)) { 00520 ast_debug(3, "Devicestate update (end) running, can't delete sched entry\n"); 00521 } 00522 00523 /* If an event is being deleted and we've fired an event changing the status at the beginning, 00524 * but haven't hit the end event yet, go ahead and set the devicestate to the current busy status */ 00525 if (event->bs_start_sched < 0 && event->bs_end_sched >= 0) { 00526 if (!calendar_is_busy(event->owner)) { 00527 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); 00528 } else { 00529 ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); 00530 } 00531 } 00532 00533 return NULL; 00534 }
| static void* do_notify | ( | void * | data | ) | [static] |
Definition at line 625 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, buf, chan, ast_channel::context, ast_datastore::data, DATASTORE_INHERIT_FOREVER, evententry::event, 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().
00626 { 00627 struct ast_calendar_event *event = data; 00628 struct ast_dial *dial = NULL; 00629 struct ast_str *apptext = NULL; 00630 struct ast_datastore *datastore; 00631 enum ast_dial_result res; 00632 struct ast_channel *chan = NULL; 00633 char *tech, *dest; 00634 char buf[8]; 00635 00636 tech = ast_strdupa(event->owner->notify_channel); 00637 00638 if ((dest = strchr(tech, '/'))) { 00639 *dest = '\0'; 00640 dest++; 00641 } else { 00642 ast_log(LOG_WARNING, "Channel should be in form Tech/Dest (was '%s')\n", tech); 00643 goto notify_cleanup; 00644 } 00645 00646 if (!(dial = ast_dial_create())) { 00647 ast_log(LOG_ERROR, "Could not create dial structure\n"); 00648 goto notify_cleanup; 00649 } 00650 00651 if (ast_dial_append(dial, tech, dest) < 0) { 00652 ast_log(LOG_ERROR, "Could not append channel\n"); 00653 goto notify_cleanup; 00654 } 00655 00656 ast_dial_set_global_timeout(dial, event->owner->notify_waittime); 00657 generate_random_string(buf, sizeof(buf)); 00658 00659 if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, 0, 0, 0, 0, 0, 0, 0, "Calendar/%s-%s", event->owner->name, buf))) { 00660 ast_log(LOG_ERROR, "Could not allocate notification channel\n"); 00661 goto notify_cleanup; 00662 } 00663 00664 chan->tech = &null_tech; 00665 chan->nativeformats = chan->writeformat = chan->rawwriteformat = 00666 chan->readformat = chan->rawreadformat = AST_FORMAT_SLINEAR; 00667 00668 if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) { 00669 ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n"); 00670 goto notify_cleanup; 00671 } 00672 00673 datastore->data = event; 00674 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 00675 00676 ao2_ref(event, +1); 00677 res = ast_channel_datastore_add(chan, datastore); 00678 00679 if (!(apptext = ast_str_create(32))) { 00680 goto notify_cleanup; 00681 } 00682 00683 if (!ast_strlen_zero(event->owner->notify_app)) { 00684 ast_str_set(&apptext, 0, "%s,%s", event->owner->notify_app, event->owner->notify_appdata); 00685 ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, ast_str_buffer(apptext)); 00686 } else { 00687 } 00688 00689 ast_verb(3, "Dialing %s for notification on calendar %s\n", event->owner->notify_channel, event->owner->name); 00690 res = ast_dial_run(dial, chan, 0); 00691 00692 if (res != AST_DIAL_RESULT_ANSWERED) { 00693 ast_verb(3, "Notification call for %s was not completed\n", event->owner->name); 00694 } else { 00695 struct ast_channel *answered; 00696 00697 answered = ast_dial_answered_steal(dial); 00698 if (ast_strlen_zero(event->owner->notify_app)) { 00699 ast_copy_string(answered->context, event->owner->notify_context, sizeof(answered->context)); 00700 ast_copy_string(answered->exten, event->owner->notify_extension, sizeof(answered->exten)); 00701 answered->priority = 1; 00702 ast_pbx_run(answered); 00703 } 00704 } 00705 00706 notify_cleanup: 00707 if (apptext) { 00708 ast_free(apptext); 00709 } 00710 if (dial) { 00711 ast_dial_destroy(dial); 00712 } 00713 if (chan) { 00714 ast_channel_release(chan); 00715 } 00716 00717 event = ast_calendar_unref_event(event); 00718 00719 return NULL; 00720 }
| static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 1598 of file res_calendar.c.
References ast_cond_timedwait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), and ast_tvnow().
01599 { 01600 for (;;) { 01601 struct timeval now = ast_tvnow(); 01602 struct timespec ts = {0,}; 01603 int res, wait; 01604 01605 ast_mutex_lock(&refreshlock); 01606 01607 if ((wait = ast_sched_wait(sched)) < 0) { 01608 wait = 1000; 01609 } 01610 01611 ts.tv_sec = (now.tv_sec + wait / 1000) + 1; 01612 res = ast_cond_timedwait(&refresh_condition, &refreshlock, &ts); 01613 01614 ast_mutex_unlock(&refreshlock); 01615 01616 ast_sched_runq(sched); 01617 } 01618 01619 return NULL; 01620 }
| static char* epoch_to_string | ( | char * | buf, | |
| size_t | buflen, | |||
| time_t | epoch | |||
| ) | [static] |
Definition at line 1382 of file res_calendar.c.
References ast_localtime(), and ast_strftime().
Referenced by handle_show_calendar().
01383 { 01384 struct ast_tm tm; 01385 struct timeval tv = { 01386 .tv_sec = epoch, 01387 }; 01388 01389 if (!epoch) { 01390 *buf = '\0'; 01391 return buf; 01392 } 01393 ast_localtime(&tv, &tm, NULL); 01394 ast_strftime(buf, buflen, "%F %r %z", &tm); 01395 01396 return buf; 01397 }
| static int event_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 245 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().
00246 { 00247 const struct ast_calendar_event *one = obj, *two = arg; 00248 return !strcmp(one->uid, two->uid) ? CMP_MATCH | CMP_STOP : 0; 00249 }
| static int event_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 239 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().
00240 { 00241 const struct ast_calendar_event *event = obj; 00242 return ast_str_hash(event->uid); 00243 }
| static void event_notification_destroy | ( | void * | data | ) | [static] |
Definition at line 579 of file res_calendar.c.
References ast_calendar_unref_event(), and evententry::event.
00580 { 00581 struct ast_calendar_event *event = data; 00582 00583 event = ast_calendar_unref_event(event); 00584 00585 }
| static void * event_notification_duplicate | ( | void * | data | ) | [static] |
Definition at line 587 of file res_calendar.c.
References ao2_ref, and evententry::event.
00588 { 00589 struct ast_calendar_event *event = data; 00590 00591 if (!event) { 00592 return NULL; 00593 } 00594 00595 ao2_ref(event, +1); 00596 00597 return event; 00598 }
| static void eventlist_destroy | ( | void * | data | ) | [static] |
| static void eventlist_destructor | ( | void * | obj | ) | [static] |
Definition at line 284 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().
00285 { 00286 struct eventlist *events = obj; 00287 struct evententry *entry; 00288 00289 while ((entry = AST_LIST_REMOVE_HEAD(events, list))) { 00290 ao2_ref(entry->event, -1); 00291 ast_free(entry); 00292 } 00293 }
| static void * eventlist_duplicate | ( | void * | data | ) | [static] |
| static struct ast_calendar* find_calendar | ( | const char * | name | ) | [static, read] |
Definition at line 231 of file res_calendar.c.
References ao2_find, ast_calendar::name, and OBJ_POINTER.
Referenced by build_calendar(), calendar_busy_exec(), calendar_query_exec(), calendar_write_exec(), calendarstate(), and handle_show_calendar().
00232 { 00233 struct ast_calendar tmp = { 00234 .name = name, 00235 }; 00236 return ao2_find(calendars, &tmp, OBJ_POINTER); 00237 }
| static struct ast_calendar_event* find_event | ( | struct ao2_container * | events, | |
| const char * | uid | |||
| ) | [static, read] |
Definition at line 251 of file res_calendar.c.
References ao2_find, OBJ_POINTER, and ast_calendar_event::uid.
Referenced by merge_events_cb().
00252 { 00253 struct ast_calendar_event tmp = { 00254 .uid = uid, 00255 }; 00256 return ao2_find(events, &tmp, OBJ_POINTER); 00257 }
| static char* generate_random_string | ( | char * | buf, | |
| size_t | size | |||
| ) | [static] |
Generate 32 byte random string (stolen from chan_sip.c).
Definition at line 601 of file res_calendar.c.
References ast_random().
00602 { 00603 long val[4]; 00604 int x; 00605 00606 for (x = 0; x < 4; x++) { 00607 val[x] = ast_random(); 00608 } 00609 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 00610 00611 return buf; 00612 }
| static char* handle_dump_sched | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1477 of file res_calendar.c.
References ast_sched_dump(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
01478 { 01479 switch(cmd) { 01480 case CLI_INIT: 01481 e->command = "calendar dump sched"; 01482 e->usage = 01483 "Usage: calendar dump sched\n" 01484 " Dump the calendar sched context"; 01485 return NULL; 01486 01487 case CLI_GENERATE: 01488 return NULL; 01489 } 01490 01491 ast_sched_dump(sched); 01492 01493 return CLI_SUCCESS; 01494 }
| static char* handle_show_calendar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1399 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, buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_calendar_event::description, ast_calendar_event::end, epoch_to_string(), evententry::event, 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::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.
01400 { 01401 #define FORMAT "%-17.17s : %-20.20s\n" 01402 #define FORMAT2 "%-12.12s: %-40.60s\n" 01403 struct ao2_iterator i; 01404 struct ast_calendar *cal; 01405 struct ast_calendar_event *event; 01406 int which = 0; 01407 char *ret = NULL; 01408 01409 switch(cmd) { 01410 case CLI_INIT: 01411 e->command = "calendar show calendar"; 01412 e->usage = 01413 "Usage: calendar show calendar <calendar name>\n" 01414 " Displays information about a calendar\n"; 01415 return NULL; 01416 01417 case CLI_GENERATE: 01418 if (a->pos != 3) { 01419 return NULL; 01420 } 01421 i = ao2_iterator_init(calendars, 0); 01422 while ((cal = ao2_iterator_next(&i))) { 01423 if (!strncasecmp(a->word, cal->name, strlen(a->word)) && ++which > a->n) { 01424 ret = ast_strdup(cal->name); 01425 cal = unref_calendar(cal); 01426 break; 01427 } 01428 cal = unref_calendar(cal); 01429 } 01430 ao2_iterator_destroy(&i); 01431 return ret; 01432 } 01433 01434 if (a->argc != 4) { 01435 return CLI_SHOWUSAGE; 01436 } 01437 01438 if (!(cal = find_calendar(a->argv[3]))) { 01439 return NULL; 01440 } 01441 01442 ast_cli(a->fd, FORMAT, "Name", cal->name); 01443 ast_cli(a->fd, FORMAT, "Notify channel", cal->notify_channel); 01444 ast_cli(a->fd, FORMAT, "Notify context", cal->notify_context); 01445 ast_cli(a->fd, FORMAT, "Notify extension", cal->notify_extension); 01446 ast_cli(a->fd, FORMAT, "Notify application", cal->notify_app); 01447 ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata); 01448 ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh); 01449 ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe); 01450 ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder); 01451 ast_cli(a->fd, "%s\n", "Events"); 01452 ast_cli(a->fd, "%s\n", "------"); 01453 01454 i = ao2_iterator_init(cal->events, 0); 01455 while ((event = ao2_iterator_next(&i))) { 01456 char buf[100]; 01457 01458 ast_cli(a->fd, FORMAT2, "Summary", event->summary); 01459 ast_cli(a->fd, FORMAT2, "Description", event->description); 01460 ast_cli(a->fd, FORMAT2, "Organizer", event->organizer); 01461 ast_cli(a->fd, FORMAT2, "Location", event->location); 01462 ast_cli(a->fd, FORMAT2, "UID", event->uid); 01463 ast_cli(a->fd, FORMAT2, "Start", epoch_to_string(buf, sizeof(buf), event->start)); 01464 ast_cli(a->fd, FORMAT2, "End", epoch_to_string(buf, sizeof(buf), event->end)); 01465 ast_cli(a->fd, FORMAT2, "Alarm", epoch_to_string(buf, sizeof(buf), event->alarm)); 01466 ast_cli(a->fd, "\n"); 01467 01468 event = ast_calendar_unref_event(event); 01469 } 01470 ao2_iterator_destroy(&i); 01471 cal = unref_calendar(cal); 01472 return CLI_SUCCESS; 01473 #undef FORMAT 01474 #undef FORMAT2 01475 }
| 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 1352 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.
01353 { 01354 #define FORMAT "%-20.20s %-10.10s %-6.6s\n" 01355 struct ao2_iterator i; 01356 struct ast_calendar *cal; 01357 01358 switch(cmd) { 01359 case CLI_INIT: 01360 e->command = "calendar show calendars"; 01361 e->usage = 01362 "Usage: calendar show calendars\n" 01363 " Lists all registered calendars.\n"; 01364 return NULL; 01365 case CLI_GENERATE: 01366 return NULL; 01367 } 01368 01369 ast_cli(a->fd, FORMAT, "Calendar", "Type", "Status"); 01370 ast_cli(a->fd, FORMAT, "--------", "----", "------"); 01371 i = ao2_iterator_init(calendars, 0); 01372 while ((cal = ao2_iterator_next(&i))) { 01373 ast_cli(a->fd, FORMAT, cal->name, cal->tech->type, calendar_is_busy(cal) ? "busy" : "free"); 01374 cal = unref_calendar(cal); 01375 } 01376 ao2_iterator_destroy(&i); 01377 01378 return CLI_SUCCESS; 01379 #undef FORMAT 01380 }
| static int load_config | ( | void * | data | ) | [static] |
Definition at line 917 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.
00918 { 00919 struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; 00920 struct ast_config *tmpcfg; 00921 00922 if (!(tmpcfg = ast_config_load2("calendar.conf", "calendar", config_flags)) || 00923 tmpcfg == CONFIG_STATUS_FILEINVALID) { 00924 ast_log(LOG_ERROR, "Unable to load config calendar.conf\n"); 00925 return -1; 00926 } 00927 00928 if (tmpcfg == CONFIG_STATUS_FILEUNCHANGED) { 00929 return 0; 00930 } 00931 00932 ast_rwlock_wrlock(&config_lock); 00933 if (calendar_config) { 00934 ast_config_destroy(calendar_config); 00935 } 00936 00937 calendar_config = tmpcfg; 00938 ast_rwlock_unlock(&config_lock); 00939 00940 return 0; 00941 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1648 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_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, and sched_context_create().
01649 { 01650 if (load_config(NULL)) { 01651 /* We don't have calendar support enabled */ 01652 return 0; 01653 } 01654 01655 if (!(calendars = ao2_container_alloc(CALENDAR_BUCKETS, calendar_hash_fn, calendar_cmp_fn))) { 01656 ast_log(LOG_ERROR, "Unable to allocate calendars container!\n"); 01657 return -1; 01658 } 01659 01660 ast_mutex_init(&refreshlock); 01661 ast_cond_init(&refresh_condition, NULL); 01662 ast_mutex_init(&reloadlock); 01663 01664 if (!(sched = sched_context_create())) { 01665 ast_log(LOG_ERROR, "Unable to create sched context\n"); 01666 return -1; 01667 } 01668 01669 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 01670 ast_log(LOG_ERROR, "Unable to start refresh thread--notifications disabled!\n"); 01671 } 01672 01673 ast_custom_function_register(&calendar_busy_function); 01674 ast_custom_function_register(&calendar_event_function); 01675 ast_custom_function_register(&calendar_query_function); 01676 ast_custom_function_register(&calendar_query_result_function); 01677 ast_custom_function_register(&calendar_write_function); 01678 ast_cli_register_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01679 01680 ast_devstate_prov_add("Calendar", calendarstate); 01681 01682 /* Since other modules depend on this, disable unloading */ 01683 ast_module_ref(ast_module_info->self); 01684 01685 return 0; 01686 }
| static int load_tech_calendars | ( | struct ast_calendar_tech * | tech | ) | [static] |
Definition at line 405 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::type, and unref_calendar().
Referenced by ast_calendar_register(), and reload().
00406 { 00407 struct ast_calendar *cal; 00408 const char *cat = NULL; 00409 const char *val; 00410 00411 if (!calendar_config) { 00412 ast_log(LOG_WARNING, "Calendar support disabled, not loading %s calendar module\n", tech->type); 00413 return -1; 00414 } 00415 00416 ast_rwlock_wrlock(&config_lock); 00417 while ((cat = ast_category_browse(calendar_config, cat))) { 00418 if (!strcasecmp(cat, "general")) { 00419 continue; 00420 } 00421 00422 if (!(val = ast_variable_retrieve(calendar_config, cat, "type")) || strcasecmp(val, tech->type)) { 00423 continue; 00424 } 00425 00426 /* A serious error occurred loading calendars from this tech and it should be disabled */ 00427 if (!(cal = build_calendar(calendar_config, cat, tech))) { 00428 ast_calendar_unregister(tech); 00429 ast_rwlock_unlock(&config_lock); 00430 return -1; 00431 } 00432 00433 cal = unref_calendar(cal); 00434 } 00435 00436 ast_rwlock_unlock(&config_lock); 00437 00438 return 0; 00439 }
| static int match_caltech_cb | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 461 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::tech.
Referenced by ast_calendar_unregister().
00462 { 00463 struct ast_calendar *cal = user_data; 00464 struct ast_calendar_tech *tech = arg; 00465 00466 if (cal->tech == tech) { 00467 return CMP_MATCH; 00468 } 00469 00470 return 0; 00471 }
| static int merge_events_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 868 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().
00869 { 00870 struct ast_calendar_event *old_event = obj, *new_event; 00871 struct ao2_container *new_events = arg; 00872 00873 /* If we don't find the old_event in new_events, then we can safely delete the old_event */ 00874 if (!(new_event = find_event(new_events, old_event->uid))) { 00875 old_event = destroy_event(old_event); 00876 return CMP_MATCH; 00877 } 00878 00879 /* We have events to merge. If any data that will affect a scheduler event has changed, 00880 * then we need to replace the scheduler event */ 00881 schedule_calendar_event(old_event->owner, old_event, new_event); 00882 00883 /* Since we don't want to mess with cancelling sched events and adding new ones, just 00884 * copy the internals of the new_event to the old_event */ 00885 copy_event_data(old_event, new_event); 00886 00887 /* Now we can go ahead and unlink the new_event from new_events and unref it so that only completely 00888 * new events remain in the container */ 00889 ao2_unlink(new_events, new_event); 00890 new_event = ast_calendar_unref_event(new_event); 00891 00892 return 0; 00893 }
| static int null_chan_write | ( | struct ast_channel * | chan, | |
| struct ast_frame * | frame | |||
| ) | [static] |
| static int reload | ( | void | ) | [static] |
Definition at line 1572 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(), evententry::list, load_config(), load_tech_calendars(), LOG_WARNING, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and ast_calendar_tech::type.
01573 { 01574 struct ast_calendar_tech *iter; 01575 01576 ast_mutex_lock(&reloadlock); 01577 01578 /* Mark existing calendars for deletion */ 01579 ao2_callback(calendars, OBJ_NODATA | OBJ_MULTIPLE, cb_pending_deletion, NULL); 01580 load_config(NULL); 01581 01582 AST_LIST_LOCK(&techs); 01583 AST_LIST_TRAVERSE(&techs, iter, list) { 01584 if (load_tech_calendars(iter)) { 01585 ast_log(LOG_WARNING, "Failed to reload %s calendars, module disabled\n", iter->type); 01586 } 01587 } 01588 AST_LIST_UNLOCK(&techs); 01589 01590 /* Delete calendars that no longer show up in the config */ 01591 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_rm_pending_deletion, NULL); 01592 01593 ast_mutex_unlock(&reloadlock); 01594 01595 return 0; 01596 }
| 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 806 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, evententry::event, ast_calendar_event::notify_sched, and ast_calendar_event::start.
Referenced by add_new_event_cb(), and merge_events_cb().
00807 { 00808 struct timeval now = ast_tvnow(); 00809 struct ast_calendar_event *event; 00810 time_t alarm_notify_sched = 0, devstate_sched_start, devstate_sched_end; 00811 int changed = 0; 00812 00813 event = cmp_event ? cmp_event : old_event; 00814 00815 ao2_lock(event); 00816 if (!cmp_event || old_event->alarm != event->alarm) { 00817 changed = 1; 00818 if (cal->autoreminder) { 00819 alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000; 00820 } else if (event->alarm) { 00821 alarm_notify_sched = (event->alarm - now.tv_sec) * 1000; 00822 } 00823 00824 /* For now, send the notification if we missed it, but the meeting hasn't happened yet */ 00825 if (event->start >= now.tv_sec) { 00826 if (alarm_notify_sched <= 0) { 00827 alarm_notify_sched = 1; 00828 } 00829 ast_mutex_lock(&refreshlock); 00830 AST_SCHED_REPLACE(old_event->notify_sched, sched, alarm_notify_sched, calendar_event_notify, old_event); 00831 ast_mutex_unlock(&refreshlock); 00832 ast_debug(3, "Calendar alarm event notification scheduled to happen in %ld ms\n", (long) alarm_notify_sched); 00833 } 00834 } 00835 00836 if (!cmp_event || old_event->start != event->start) { 00837 changed = 1; 00838 devstate_sched_start = (event->start - now.tv_sec) * 1000; 00839 00840 if (devstate_sched_start < 1) { 00841 devstate_sched_start = 1; 00842 } 00843 00844 ast_mutex_lock(&refreshlock); 00845 AST_SCHED_REPLACE(old_event->bs_start_sched, sched, devstate_sched_start, calendar_devstate_change, old_event); 00846 ast_mutex_unlock(&refreshlock); 00847 ast_debug(3, "Calendar bs_start event notification scheduled to happen in %ld ms\n", (long) devstate_sched_start); 00848 } 00849 00850 if (!cmp_event || old_event->end != event->end) { 00851 changed = 1; 00852 devstate_sched_end = (event->end - now.tv_sec) * 1000; 00853 ast_mutex_lock(&refreshlock); 00854 AST_SCHED_REPLACE(old_event->bs_end_sched, sched, devstate_sched_end, calendar_devstate_change, old_event); 00855 ast_mutex_unlock(&refreshlock); 00856 ast_debug(3, "Calendar bs_end event notification scheduled to happen in %ld ms\n", (long) devstate_sched_end); 00857 } 00858 00859 if (changed) { 00860 ast_cond_signal(&refresh_condition); 00861 } 00862 00863 ao2_unlock(event); 00864 00865 return 0; 00866 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1623 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, evententry::list, ast_calendar_tech::module, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.
01624 { 01625 struct ast_calendar_tech *tech; 01626 01627 ast_devstate_prov_del("calendar"); 01628 ast_custom_function_unregister(&calendar_busy_function); 01629 ast_custom_function_unregister(&calendar_event_function); 01630 ast_custom_function_unregister(&calendar_query_function); 01631 ast_custom_function_unregister(&calendar_query_result_function); 01632 ast_custom_function_unregister(&calendar_write_function); 01633 ast_cli_unregister_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01634 01635 /* Remove all calendars */ 01636 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); 01637 01638 AST_LIST_LOCK(&techs); 01639 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, tech, list) { 01640 ast_unload_resource(tech->module, 0); 01641 } 01642 AST_LIST_TRAVERSE_SAFE_END; 01643 AST_LIST_UNLOCK(&techs); 01644 01645 return 0; 01646 }
| static struct ast_calendar* unref_calendar | ( | struct ast_calendar * | cal | ) | [static, read] |
Definition at line 213 of file res_calendar.c.
References ao2_ref.
Referenced by build_calendar(), calendar_query_exec(), calendar_write_exec(), handle_show_calendar(), handle_show_calendars(), and load_tech_calendars().
00214 { 00215 ao2_ref(cal, -1); 00216 return NULL; 00217 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 1691 of file res_calendar.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1691 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 965 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ast_cli_entry calendar_cli[] [static] |
Initial value:
{
AST_CLI_DEFINE(handle_show_calendar, "Display information about a calendar"),
AST_CLI_DEFINE(handle_show_calendars, "Show registered calendars"),
AST_CLI_DEFINE(handle_dump_sched, "Dump calendar sched context"),
}
Definition at line 1496 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ast_config* calendar_config [static] |
Definition at line 193 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 1551 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 1145 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 1252 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 1346 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ao2_container* calendars [static] |
Definition at line 161 of file res_calendar.c.
ast_rwlock_t config_lock = { 0 } [static] |
Definition at line 194 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 173 of file res_calendar.c.
struct ast_datastore_info eventlist_datastore_info [static] |
Initial value:
{
.type = "CalendarEventList",
.destroy = eventlist_destroy,
.duplicate = eventlist_duplicate,
}
Definition at line 179 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 619 of file res_calendar.c.
ast_cond_t refresh_condition [static] |
Definition at line 165 of file res_calendar.c.
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
Definition at line 163 of file res_calendar.c.
ast_mutex_t refreshlock [static] |
Definition at line 164 of file res_calendar.c.
Referenced by caldav_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().
ast_mutex_t reloadlock [static] |
Definition at line 166 of file res_calendar.c.
struct sched_context* sched [static] |
Definition at line 162 of file res_calendar.c.
1.5.6