#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 "%-10.10s %-30.30s\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 char * | handle_show_calendars_types (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command to list of all calendars types currently loaded on the backend. | |
| 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 = AST_BUILDOPT_SUM, .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 = { {0} , 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 ast_sched_context * | sched |
Definition in file res_calendar.c.
| #define CALENDAR_BUCKETS 19 |
Definition at line 211 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 "%-10.10s %-30.30s\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 1862 of file res_calendar.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 1862 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 1070 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().
01071 { 01072 struct evententry *entry, *iter; 01073 int event_startdiff = abs(start - event->start); 01074 int event_enddiff = abs(end - event->end); 01075 int i = 0; 01076 01077 if (!(entry = ast_calloc(1, sizeof(*entry)))) { 01078 ast_log(LOG_ERROR, "Unable to allocate memory for event list\n"); 01079 return -1; 01080 } 01081 01082 entry->event = event; 01083 ao2_ref(event, +1); 01084 01085 if (start == end) { 01086 AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) { 01087 int startdiff = abs(iter->event->start - start); 01088 01089 ast_debug(10, "Comparing %s with startdiff %d to %s with startdiff %d\n", event->summary, event_startdiff, iter->event->summary, startdiff); 01090 ++i; 01091 if (startdiff > event_startdiff) { 01092 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01093 return i; 01094 } 01095 if (startdiff == event_startdiff) { 01096 int enddiff = abs(iter->event->end - end); 01097 01098 if (enddiff > event_enddiff) { 01099 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01100 return i; 01101 } 01102 if (event_startdiff == enddiff) { 01103 if (strcmp(event->uid, iter->event->uid) < 0) { 01104 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01105 return i; 01106 } 01107 } 01108 } 01109 } 01110 AST_LIST_TRAVERSE_SAFE_END; 01111 01112 AST_LIST_INSERT_TAIL(events, entry, list); 01113 01114 return i; 01115 } 01116 01117 AST_LIST_TRAVERSE_SAFE_BEGIN(events, iter, list) { 01118 ++i; 01119 if (iter->event->start > event->start) { 01120 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01121 return i; 01122 } 01123 01124 if (iter->event->start == event->start) { 01125 if ((iter->event->end - iter->event->start) == (event->end - event->start)) { 01126 if (strcmp(event->uid, iter->event->uid) < 0) { 01127 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01128 return i; 01129 } 01130 } 01131 if ((iter->event->end - iter->event->start) < (event->end - event->start)) { 01132 AST_LIST_INSERT_BEFORE_CURRENT(entry, list); 01133 return i; 01134 } 01135 } 01136 } 01137 AST_LIST_TRAVERSE_SAFE_END; 01138 01139 AST_LIST_INSERT_TAIL(events, entry, list); 01140 01141 return i; 01142 }
| static int add_new_event_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 995 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().
00996 { 00997 struct ast_calendar_event *new_event = obj; 00998 struct ao2_container *events = arg; 00999 01000 ao2_link(events, new_event); 01001 schedule_calendar_event(new_event->owner, new_event, NULL); 01002 return CMP_MATCH; 01003 }
| 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 626 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().
00627 { 00628 ast_debug(3, "Clearing all events for calendar %s\n", cal->name); 00629 00630 ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, clear_events_cb, NULL); 00631 }
| struct ast_config* ast_calendar_config_acquire | ( | void | ) | [read] |
Grab and lock pointer to the calendar config (read only).
Definition at line 249 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().
00250 { 00251 ast_rwlock_rdlock(&config_lock); 00252 00253 if (!calendar_config) { 00254 ast_rwlock_unlock(&config_lock); 00255 return NULL; 00256 } 00257 00258 return calendar_config; 00259 }
| void ast_calendar_config_release | ( | void | ) |
Release the calendar config.
Definition at line 261 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().
00262 { 00263 ast_rwlock_unlock(&config_lock); 00264 }
| 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 633 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(), parse_tag(), and startelm().
00634 { 00635 struct ast_calendar_event *event; 00636 if (!(event = ao2_alloc(sizeof(*event), calendar_event_destructor))) { 00637 return NULL; 00638 } 00639 00640 if (ast_string_field_init(event, 32)) { 00641 event = ast_calendar_unref_event(event); 00642 return NULL; 00643 } 00644 00645 event->owner = cal; 00646 event->notify_sched = -1; 00647 event->bs_start_sched = -1; 00648 event->bs_end_sched = -1; 00649 00650 AST_LIST_HEAD_INIT_NOLOCK(&event->attendees); 00651 00652 return event; 00653 }
| struct ao2_container* ast_calendar_event_container_alloc | ( | void | ) | [read] |
Allocate an astobj2 container for ast_calendar_event objects.
Definition at line 655 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().
00656 { 00657 return ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn); 00658 }
| 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 1005 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().
01006 { 01007 /* Loop through all events attached to the calendar. If there is a matching new event 01008 * merge its data over and handle any schedule changes that need to be made. Then remove 01009 * the new_event from new_events so that we are left with only new_events that we can add later. */ 01010 ao2_callback(cal->events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, merge_events_cb, new_events); 01011 01012 /* Now, we should only have completely new events in new_events. Loop through and add them */ 01013 ao2_callback(new_events, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, add_new_event_cb, cal->events); 01014 }
| 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 522 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().
00523 { 00524 struct ast_calendar_tech *iter; 00525 00526 AST_LIST_LOCK(&techs); 00527 AST_LIST_TRAVERSE(&techs, iter, list) { 00528 if(!strcasecmp(tech->type, iter->type)) { 00529 ast_log(LOG_WARNING, "Already have a handler for calendar type '%s'\n", tech->type); 00530 AST_LIST_UNLOCK(&techs); 00531 return -1; 00532 } 00533 } 00534 AST_LIST_INSERT_HEAD(&techs, tech, list); 00535 AST_LIST_UNLOCK(&techs); 00536 00537 ast_verb(2, "Registered calendar type '%s' (%s)\n", tech->type, tech->description); 00538 00539 return load_tech_calendars(tech); 00540 }
| 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 312 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(), endelm(), event_notification_destroy(), handle_show_calendar(), icalendar_add_event(), merge_events_cb(), and parse_tag().
00313 { 00314 ao2_ref(event, -1); 00315 return NULL; 00316 }
| 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 554 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().
00555 { 00556 struct ast_calendar_tech *iter; 00557 00558 AST_LIST_LOCK(&techs); 00559 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, iter, list) { 00560 if (iter != tech) { 00561 continue; 00562 } 00563 00564 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, match_caltech_cb, tech); 00565 00566 AST_LIST_REMOVE_CURRENT(list); 00567 ast_verb(2, "Unregistered calendar type '%s'\n", tech->type); 00568 break; 00569 } 00570 AST_LIST_TRAVERSE_SAFE_END; 00571 AST_LIST_UNLOCK(&techs); 00572 00573 }
| static struct ast_calendar* build_calendar | ( | struct ast_config * | cfg, | |
| const char * | cat, | |||
| const struct ast_calendar_tech * | tech | |||
| ) | [static, read] |
Definition at line 390 of file res_calendar.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_unlink, ast_cond_init, ast_free, ast_log(), ast_pthread_create, AST_PTHREADT_NULL, ast_strdup, ast_string_field_init, ast_string_field_set, ast_strip(), ast_variable_browse(), ast_variable_new(), ast_calendar::autoreminder, CALENDAR_BUCKETS, calendar_destructor(), event_cmp_fn(), event_hash_fn(), ast_calendar::events, find_calendar(), last, ast_calendar_tech::load_calendar, LOG_ERROR, LOG_WARNING, ast_variable::name, name, ast_variable::next, ast_calendar::notify_waittime, ast_calendar::pending_deletion, ast_calendar::refresh, strsep(), ast_calendar::tech, ast_calendar::thread, ast_calendar::timeframe, ast_calendar::unload, unref_calendar(), value, ast_variable::value, var, and ast_calendar::vars.
Referenced by load_tech_calendars().
00391 { 00392 struct ast_calendar *cal; 00393 struct ast_variable *v, *last = NULL; 00394 int new_calendar = 0; 00395 00396 if (!(cal = find_calendar(cat))) { 00397 new_calendar = 1; 00398 if (!(cal = ao2_alloc(sizeof(*cal), calendar_destructor))) { 00399 ast_log(LOG_ERROR, "Could not allocate calendar structure. Stopping.\n"); 00400 return NULL; 00401 } 00402 00403 if (!(cal->events = ao2_container_alloc(CALENDAR_BUCKETS, event_hash_fn, event_cmp_fn))) { 00404 ast_log(LOG_ERROR, "Could not allocate events container for %s\n", cat); 00405 cal = unref_calendar(cal); 00406 return NULL; 00407 } 00408 00409 if (ast_string_field_init(cal, 32)) { 00410 ast_log(LOG_ERROR, "Couldn't create string fields for %s\n", cat); 00411 cal = unref_calendar(cal); 00412 return NULL; 00413 } 00414 } else { 00415 cal->pending_deletion = 0; 00416 } 00417 00418 ast_string_field_set(cal, name, cat); 00419 cal->tech = tech; 00420 00421 cal->refresh = 3600; 00422 cal->timeframe = 60; 00423 cal->notify_waittime = 30000; 00424 00425 for (v = ast_variable_browse(cfg, cat); v; v = v->next) { 00426 if (!strcasecmp(v->name, "autoreminder")) { 00427 cal->autoreminder = atoi(v->value); 00428 } else if (!strcasecmp(v->name, "channel")) { 00429 ast_string_field_set(cal, notify_channel, v->value); 00430 } else if (!strcasecmp(v->name, "context")) { 00431 ast_string_field_set(cal, notify_context, v->value); 00432 } else if (!strcasecmp(v->name, "extension")) { 00433 ast_string_field_set(cal, notify_extension, v->value); 00434 } else if (!strcasecmp(v->name, "waittime")) { 00435 int i = atoi(v->value); 00436 if (i > 0) { 00437 cal->notify_waittime = 1000 * i; 00438 } 00439 } else if (!strcasecmp(v->name, "app")) { 00440 ast_string_field_set(cal, notify_app, v->value); 00441 } else if (!strcasecmp(v->name, "appdata")) { 00442 ast_string_field_set(cal, notify_appdata, v->value); 00443 } else if (!strcasecmp(v->name, "refresh")) { 00444 cal->refresh = atoi(v->value); 00445 } else if (!strcasecmp(v->name, "timeframe")) { 00446 cal->timeframe = atoi(v->value); 00447 } else if (!strcasecmp(v->name, "setvar")) { 00448 char *name, *value; 00449 struct ast_variable *var; 00450 00451 if ((name = (value = ast_strdup(v->value)))) { 00452 strsep(&value, "="); 00453 if (value) { 00454 if ((var = ast_variable_new(ast_strip(name), ast_strip(value), ""))) { 00455 if (last) { 00456 last->next = var; 00457 } else { 00458 cal->vars = var; 00459 } 00460 last = var; 00461 } 00462 } else { 00463 ast_log(LOG_WARNING, "Malformed argument. Should be '%s: variable=value'\n", v->name); 00464 } 00465 ast_free(name); 00466 } 00467 } 00468 } 00469 00470 if (new_calendar) { 00471 cal->thread = AST_PTHREADT_NULL; 00472 ast_cond_init(&cal->unload, NULL); 00473 ao2_link(calendars, cal); 00474 if (ast_pthread_create(&cal->thread, NULL, cal->tech->load_calendar, cal)) { 00475 /* If we start failing to create threads, go ahead and return NULL 00476 * and the tech module will be unregistered 00477 */ 00478 ao2_unlink(calendars, cal); 00479 cal = unref_calendar(cal); 00480 } 00481 } 00482 00483 return cal; 00484 }
| static int calendar_busy_callback | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 352 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().
00353 { 00354 struct ast_calendar_event *event = obj; 00355 int *is_busy = arg; 00356 struct timeval tv = ast_tvnow(); 00357 00358 if (tv.tv_sec >= event->start && tv.tv_sec <= event->end && event->busy_state > AST_CALENDAR_BS_FREE) { 00359 *is_busy = 1; 00360 return CMP_STOP; 00361 } 00362 00363 return 0; 00364 }
| 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 1044 of file res_calendar.c.
References ast_log(), ast_strlen_zero(), calendar_is_busy(), find_calendar(), and LOG_WARNING.
01045 { 01046 struct ast_calendar *cal; 01047 01048 if (ast_strlen_zero(data)) { 01049 ast_log(LOG_WARNING, "CALENDAR_BUSY requires an argument: CALENDAR_BUSY(<calendar_name>)\n"); 01050 return -1; 01051 } 01052 01053 cal = find_calendar(data); 01054 01055 if (!cal) { 01056 ast_log(LOG_WARNING, "Could not find calendar '%s'\n", data); 01057 return -1; 01058 } 01059 01060 strcpy(buf, calendar_is_busy(cal) ? "1" : "0"); 01061 01062 return 0; 01063 }
| static int calendar_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 278 of file res_calendar.c.
References CMP_MATCH, CMP_STOP, and ast_calendar::name.
Referenced by load_module().
00279 { 00280 const struct ast_calendar *one = obj, *two = arg; 00281 return !strcasecmp(one->name, two->name) ? CMP_MATCH | CMP_STOP: 0; 00282 }
| static void calendar_destructor | ( | void * | obj | ) | [static] |
Definition at line 318 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_variables_destroy(), ast_calendar::events, ast_calendar::name, ast_calendar::tech, ast_calendar::tech_pvt, ast_calendar::thread, ast_calendar::unload, ast_calendar::unloading, ast_calendar_tech::unref_calendar, and ast_calendar::vars.
Referenced by build_calendar().
00319 { 00320 struct ast_calendar *cal = obj; 00321 00322 ast_debug(3, "Destroying calendar %s\n", cal->name); 00323 00324 ao2_lock(cal); 00325 cal->unloading = 1; 00326 ast_cond_signal(&cal->unload); 00327 pthread_join(cal->thread, NULL); 00328 if (cal->tech_pvt) { 00329 cal->tech_pvt = cal->tech->unref_calendar(cal->tech_pvt); 00330 } 00331 ast_calendar_clear_events(cal); 00332 ast_string_field_free_memory(cal); 00333 if (cal->vars) { 00334 ast_variables_destroy(cal->vars); 00335 cal->vars = NULL; 00336 } 00337 ao2_ref(cal->events, -1); 00338 ao2_unlock(cal); 00339 }
| static int calendar_devstate_change | ( | const void * | data | ) | [static] |
Definition at line 844 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().
00845 { 00846 struct ast_calendar_event *event = (struct ast_calendar_event *)data; 00847 struct timeval now = ast_tvnow(); 00848 int is_end_event; 00849 00850 if (!event) { 00851 ast_log(LOG_WARNING, "Event was NULL!\n"); 00852 return 0; 00853 } 00854 00855 ao2_ref(event, +1); 00856 00857 is_end_event = event->end <= now.tv_sec; 00858 00859 if (is_end_event) { 00860 event->bs_end_sched = -1; 00861 } else { 00862 event->bs_start_sched = -1; 00863 } 00864 00865 /* We can have overlapping events, so ignore the event->busy_state and check busy state 00866 * based on all events in the calendar */ 00867 if (!calendar_is_busy(event->owner)) { 00868 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); 00869 } else { 00870 ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); 00871 } 00872 00873 event = ast_calendar_unref_event(event); 00874 00875 return 0; 00876 }
| static void calendar_event_destructor | ( | void * | obj | ) | [static] |
Definition at line 575 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().
00576 { 00577 struct ast_calendar_event *event = obj; 00578 struct ast_calendar_attendee *attendee; 00579 00580 ast_debug(3, "Destroying event for calendar '%s'\n", event->owner->name); 00581 ast_string_field_free_memory(event); 00582 while ((attendee = AST_LIST_REMOVE_HEAD(&event->attendees, next))) { 00583 if (attendee->data) { 00584 ast_free(attendee->data); 00585 } 00586 ast_free(attendee); 00587 } 00588 }
| static int calendar_event_notify | ( | const void * | data | ) | [static] |
Definition at line 820 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().
00821 { 00822 struct ast_calendar_event *event = (void *)data; 00823 int res = -1; 00824 pthread_t notify_thread = AST_PTHREADT_NULL; 00825 00826 if (!(event && event->owner)) { 00827 ast_log(LOG_ERROR, "Extremely low-cal...in fact cal is NULL!\n"); 00828 return res; 00829 } 00830 00831 ao2_ref(event, +1); 00832 event->notify_sched = -1; 00833 00834 if (ast_pthread_create_background(¬ify_thread, NULL, do_notify, event) < 0) { 00835 ast_log(LOG_ERROR, "Could not create notification thread\n"); 00836 return res; 00837 } 00838 00839 res = 0; 00840 00841 return res; 00842 }
| static int calendar_event_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1656 of file res_calendar.c.
References ast_channel_datastore_find(), ast_channel_lock, ast_channel_name(), 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, evententry::event, ast_calendar_event::location, LOG_WARNING, ast_calendar::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.
01657 { 01658 struct ast_datastore *datastore; 01659 struct ast_calendar_event *event; 01660 01661 if (ast_strlen_zero(data)) { 01662 ast_log(LOG_WARNING, "%s requires an argument\n", cmd); 01663 return -1; 01664 } 01665 01666 ast_channel_lock(chan); 01667 if (!(datastore = ast_channel_datastore_find(chan, &event_notification_datastore, NULL))) { 01668 ast_log(LOG_WARNING, "There is no event notification datastore on '%s'!\n", ast_channel_name(chan)); 01669 ast_channel_unlock(chan); 01670 return -1; 01671 } 01672 ast_channel_unlock(chan); 01673 01674 if (!(event = datastore->data)) { 01675 ast_log(LOG_WARNING, "The datastore contains no data!\n"); 01676 return -1; 01677 } 01678 01679 if (!strcasecmp(data, "summary")) { 01680 ast_copy_string(buf, event->summary, len); 01681 } else if (!strcasecmp(data, "description")) { 01682 ast_copy_string(buf, event->description, len); 01683 } else if (!strcasecmp(data, "organizer")) { 01684 ast_copy_string(buf, event->organizer, len); 01685 } else if (!strcasecmp(data, "location")) { 01686 ast_copy_string(buf, event->location, len); 01687 } else if (!strcasecmp(data, "categories")) { 01688 ast_copy_string(buf, event->categories, len); 01689 } else if (!strcasecmp(data, "priority")) { 01690 snprintf(buf, len, "%d", event->priority); 01691 } else if (!strcasecmp(data, "calendar")) { 01692 ast_copy_string(buf, event->owner->name, len); 01693 } else if (!strcasecmp(data, "uid")) { 01694 ast_copy_string(buf, event->uid, len); 01695 } else if (!strcasecmp(data, "start")) { 01696 snprintf(buf, len, "%ld", (long)event->start); 01697 } else if (!strcasecmp(data, "end")) { 01698 snprintf(buf, len, "%ld", (long)event->end); 01699 } else if (!strcasecmp(data, "busystate")) { 01700 snprintf(buf, len, "%d", event->busy_state); 01701 } else if (!strcasecmp(data, "attendees")) { 01702 calendar_join_attendees(event, buf, len); 01703 } 01704 01705 01706 return 0; 01707 }
| static int calendar_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 272 of file res_calendar.c.
References ast_str_case_hash(), and ast_calendar::name.
Referenced by load_module().
00273 { 00274 const struct ast_calendar *cal = obj; 00275 return ast_str_case_hash(cal->name); 00276 }
| static int calendar_is_busy | ( | struct ast_calendar * | cal | ) | [static] |
Definition at line 366 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().
00367 { 00368 int is_busy = 0; 00369 00370 ao2_callback(cal->events, OBJ_NODATA, calendar_busy_callback, &is_busy); 00371 00372 return is_busy; 00373 }
| static void calendar_join_attendees | ( | struct ast_calendar_event * | event, | |
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1250 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().
01251 { 01252 struct ast_str *tmp; 01253 struct ast_calendar_attendee *attendee; 01254 01255 if (!(tmp = ast_str_create(32))) { 01256 ast_log(LOG_ERROR, "Could not allocate memory for attendees!\n"); 01257 return; 01258 } 01259 01260 AST_LIST_TRAVERSE(&event->attendees, attendee, next) { 01261 ast_str_append(&tmp, 0, "%s%s", attendee == AST_LIST_FIRST(&event->attendees) ? "" : ",", attendee->data); 01262 } 01263 01264 ast_copy_string(buf, ast_str_buffer(tmp), len); 01265 ast_free(tmp); 01266 }
| static int calendar_query_exec | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1164 of file res_calendar.c.
References add_event_to_list(), ao2_alloc, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, args, AST_APP_ARG, ast_calendar_unref_event(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_debug, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_datastore::data, DATASTORE_INHERIT_FOREVER, ast_calendar_event::end, 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().
01165 { 01166 struct ast_calendar *cal; 01167 struct ao2_iterator i; 01168 struct ast_calendar_event *event; 01169 struct eventlist *events; 01170 time_t start = INT_MIN, end = INT_MAX; 01171 struct ast_datastore *eventlist_datastore; 01172 AST_DECLARE_APP_ARGS(args, 01173 AST_APP_ARG(calendar); 01174 AST_APP_ARG(start); 01175 AST_APP_ARG(end); 01176 ); 01177 01178 if (!chan) { 01179 ast_log(LOG_WARNING, "%s requires a channel to store the data on\n", cmd); 01180 return -1; 01181 } 01182 01183 AST_STANDARD_APP_ARGS(args, data); 01184 01185 if (ast_strlen_zero(args.calendar)) { 01186 ast_log(LOG_WARNING, "%s requires a calendar argument\n", cmd); 01187 return -1; 01188 } 01189 01190 if (!(cal = find_calendar(args.calendar))) { 01191 ast_log(LOG_WARNING, "Unknown calendar '%s'\n", args.calendar); 01192 return -1; 01193 } 01194 01195 if (!(events = ao2_alloc(sizeof(*events), eventlist_destructor))) { 01196 ast_log(LOG_ERROR, "Unable to allocate memory for event list\n"); 01197 cal = unref_calendar(cal); 01198 return -1; 01199 } 01200 01201 if (!ast_strlen_zero(args.start)) { 01202 start = atoi(args.start); 01203 } 01204 01205 if (!ast_strlen_zero(args.end)) { 01206 end = atoi(args.end); 01207 } 01208 01209 i = ao2_iterator_init(cal->events, 0); 01210 while ((event = ao2_iterator_next(&i))) { 01211 if (!(start > event->end || end < event->start)) { 01212 ast_debug(10, "%s (%ld - %ld) overlapped with (%ld - %ld)\n", event->summary, (long) event->start, (long) event->end, (long) start, (long) end); 01213 if (add_event_to_list(events, event, start, end) < 0) { 01214 event = ast_calendar_unref_event(event); 01215 ao2_iterator_destroy(&i); 01216 return -1; 01217 } 01218 } 01219 01220 event = ast_calendar_unref_event(event); 01221 } 01222 ao2_iterator_destroy(&i); 01223 01224 ast_channel_lock(chan); 01225 do { 01226 generate_random_string(buf, len); 01227 } while (ast_channel_datastore_find(chan, &eventlist_datastore_info, buf)); 01228 ast_channel_unlock(chan); 01229 01230 if (!(eventlist_datastore = ast_datastore_alloc(&eventlist_datastore_info, buf))) { 01231 ast_log(LOG_ERROR, "Could not allocate datastore!\n"); 01232 return -1; 01233 } 01234 01235 eventlist_datastore->inheritance = DATASTORE_INHERIT_FOREVER; 01236 eventlist_datastore->data = events; 01237 01238 ast_channel_lock(chan); 01239 ast_channel_datastore_add(chan, eventlist_datastore); 01240 ast_channel_unlock(chan); 01241 01242 return 0; 01243 }
| static int calendar_query_result_exec | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 1268 of file res_calendar.c.
References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_name(), 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, events, evententry::list, ast_calendar_event::location, LOG_WARNING, ast_calendar::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.
01269 { 01270 struct ast_datastore *datastore; 01271 struct eventlist *events; 01272 struct evententry *entry; 01273 int row = 1; 01274 size_t listlen = 0; 01275 AST_DECLARE_APP_ARGS(args, 01276 AST_APP_ARG(id); 01277 AST_APP_ARG(field); 01278 AST_APP_ARG(row); 01279 ); 01280 01281 if (!chan) { 01282 ast_log(LOG_WARNING, "%s requires a channel\n", cmd); 01283 return -1; 01284 } 01285 01286 AST_STANDARD_APP_ARGS(args, data); 01287 01288 if (ast_strlen_zero(args.id) || ast_strlen_zero(args.field)) { 01289 ast_log(LOG_WARNING, "%s requires an id and a field", cmd); 01290 return -1; 01291 } 01292 01293 ast_channel_lock(chan); 01294 if (!(datastore = ast_channel_datastore_find(chan, &eventlist_datastore_info, args.id))) { 01295 ast_log(LOG_WARNING, "There is no event notification datastore with id '%s' on '%s'!\n", args.id, ast_channel_name(chan)); 01296 ast_channel_unlock(chan); 01297 return -1; 01298 } 01299 ast_channel_unlock(chan); 01300 01301 if (!(events = datastore->data)) { 01302 ast_log(LOG_WARNING, "The datastore contains no data!\n"); 01303 return -1; 01304 } 01305 01306 if (!ast_strlen_zero(args.row)) { 01307 row = atoi(args.row); 01308 } 01309 01310 AST_LIST_TRAVERSE(events, entry, list) { 01311 listlen++; 01312 } 01313 01314 if (!strcasecmp(args.field, "getnum")) { 01315 snprintf(buf, len, "%zu", listlen); 01316 return 0; 01317 } 01318 01319 AST_LIST_TRAVERSE(events, entry, list) { 01320 if (--row) { 01321 continue; 01322 } 01323 if (!strcasecmp(args.field, "summary")) { 01324 ast_copy_string(buf, entry->event->summary, len); 01325 } else if (!strcasecmp(args.field, "description")) { 01326 ast_copy_string(buf, entry->event->description, len); 01327 } else if (!strcasecmp(args.field, "organizer")) { 01328 ast_copy_string(buf, entry->event->organizer, len); 01329 } else if (!strcasecmp(args.field, "location")) { 01330 ast_copy_string(buf, entry->event->location, len); 01331 } else if (!strcasecmp(args.field, "categories")) { 01332 ast_copy_string(buf, entry->event->categories, len); 01333 } else if (!strcasecmp(args.field, "priority")) { 01334 snprintf(buf, len, "%d", entry->event->priority); 01335 } else if (!strcasecmp(args.field, "calendar")) { 01336 ast_copy_string(buf, entry->event->owner->name, len); 01337 } else if (!strcasecmp(args.field, "uid")) { 01338 ast_copy_string(buf, entry->event->uid, len); 01339 } else if (!strcasecmp(args.field, "start")) { 01340 snprintf(buf, len, "%ld", (long) entry->event->start); 01341 } else if (!strcasecmp(args.field, "end")) { 01342 snprintf(buf, len, "%ld", (long) entry->event->end); 01343 } else if (!strcasecmp(args.field, "busystate")) { 01344 snprintf(buf, len, "%d", entry->event->busy_state); 01345 } else if (!strcasecmp(args.field, "attendees")) { 01346 calendar_join_attendees(entry->event, buf, len); 01347 } else { 01348 ast_log(LOG_WARNING, "Unknown field '%s'\n", args.field); 01349 } 01350 break; 01351 } 01352 01353 return 0; 01354 }
| static int calendar_write_exec | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 1361 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_tvnow(), ast_calendar_event::end, evententry::event, find_calendar(), LOG_ERROR, LOG_WARNING, ast_calendar::name, pbx_builtin_setvar_helper(), ast_calendar_event::start, ast_calendar::tech, unref_calendar(), and ast_calendar_tech::write_event.
01362 { 01363 int i, j, ret = -1; 01364 char *val_dup = NULL; 01365 struct ast_calendar *cal = NULL; 01366 struct ast_calendar_event *event = NULL; 01367 struct timeval tv = ast_tvnow(); 01368 AST_DECLARE_APP_ARGS(fields, 01369 AST_APP_ARG(field)[10]; 01370 ); 01371 AST_DECLARE_APP_ARGS(values, 01372 AST_APP_ARG(value)[10]; 01373 ); 01374 01375 if (!(val_dup = ast_strdup(value))) { 01376 ast_log(LOG_ERROR, "Could not allocate memory for values\n"); 01377 goto write_cleanup; 01378 } 01379 01380 AST_STANDARD_APP_ARGS(fields, data); 01381 AST_STANDARD_APP_ARGS(values, val_dup); 01382 01383 /* XXX Eventually we will support unnamed calendars, so if we don't find one, we parse 01384 * for a calendar type and create it */ 01385 if (!(cal = find_calendar(fields.field[0]))) { 01386 ast_log(LOG_WARNING, "Couldn't find calendar '%s'\n", fields.field[0]); 01387 goto write_cleanup; 01388 } 01389 01390 if (!(cal->tech->write_event)) { 01391 ast_log(LOG_WARNING, "Calendar '%s' has no write function!\n", cal->name); 01392 goto write_cleanup; 01393 } 01394 01395 if (!(event = ast_calendar_event_alloc(cal))) { 01396 goto write_cleanup; 01397 } 01398 01399 if (ast_strlen_zero(fields.field[0])) { 01400 ast_log(LOG_WARNING, "CALENDAR_WRITE requires a calendar name!\n"); 01401 goto write_cleanup; 01402 } 01403 01404 if (fields.argc - 1 != values.argc) { 01405 ast_log(LOG_WARNING, "CALENDAR_WRITE should have the same number of fields (%d) and values (%d)!\n", fields.argc - 1, values.argc); 01406 goto write_cleanup; 01407 } 01408 01409 event->owner = cal; 01410 01411 for (i = 1, j = 0; i < fields.argc; i++, j++) { 01412 if (!strcasecmp(fields.field[i], "summary")) { 01413 ast_string_field_set(event, summary, values.value[j]); 01414 } else if (!strcasecmp(fields.field[i], "description")) { 01415 ast_string_field_set(event, description, values.value[j]); 01416 } else if (!strcasecmp(fields.field[i], "organizer")) { 01417 ast_string_field_set(event, organizer, values.value[j]); 01418 } else if (!strcasecmp(fields.field[i], "location")) { 01419 ast_string_field_set(event, location, values.value[j]); 01420 } else if (!strcasecmp(fields.field[i], "categories")) { 01421 ast_string_field_set(event, categories, values.value[j]); 01422 } else if (!strcasecmp(fields.field[i], "priority")) { 01423 event->priority = atoi(values.value[j]); 01424 } else if (!strcasecmp(fields.field[i], "uid")) { 01425 ast_string_field_set(event, uid, values.value[j]); 01426 } else if (!strcasecmp(fields.field[i], "start")) { 01427 event->start = atoi(values.value[j]); 01428 } else if (!strcasecmp(fields.field[i], "end")) { 01429 event->end = atoi(values.value[j]); 01430 } else if (!strcasecmp(fields.field[i], "busystate")) { 01431 event->busy_state = atoi(values.value[j]); 01432 } else { 01433 ast_log(LOG_WARNING, "Unknown calendar event field '%s'\n", fields.field[i]); 01434 } 01435 } 01436 01437 if (!event->start) { 01438 event->start = tv.tv_sec; 01439 } 01440 01441 if (!event->end) { 01442 event->end = tv.tv_sec; 01443 } 01444 01445 if((ret = cal->tech->write_event(event))) { 01446 ast_log(LOG_WARNING, "Writing event to calendar '%s' failed!\n", cal->name); 01447 } 01448 01449 write_cleanup: 01450 if (ret) { 01451 pbx_builtin_setvar_helper(chan, "CALENDAR_SUCCESS", "0"); 01452 } else { 01453 pbx_builtin_setvar_helper(chan, "CALENDAR_SUCCESS", "1"); 01454 } 01455 if (cal) { 01456 cal = unref_calendar(cal); 01457 } 01458 if (event) { 01459 event = ast_calendar_unref_event(event); 01460 } 01461 if (val_dup) { 01462 ast_free(val_dup); 01463 } 01464 01465 return ret; 01466 }
| static enum ast_device_state calendarstate | ( | const char * | data | ) | [static] |
Definition at line 375 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().
00376 { 00377 struct ast_calendar *cal; 00378 00379 if (ast_strlen_zero(data) || (!(cal = find_calendar(data)))) { 00380 return AST_DEVICE_INVALID; 00381 } 00382 00383 if (cal->tech->is_busy) { 00384 return cal->tech->is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; 00385 } 00386 00387 return calendar_is_busy(cal) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE; 00388 }
| static int cb_pending_deletion | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1714 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::pending_deletion.
Referenced by reload().
01715 { 01716 struct ast_calendar *cal = user_data; 01717 01718 cal->pending_deletion = 1; 01719 01720 return CMP_MATCH; 01721 }
| static int cb_rm_pending_deletion | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1723 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::pending_deletion.
Referenced by reload().
01724 { 01725 struct ast_calendar *cal = user_data; 01726 01727 return cal->pending_deletion ? CMP_MATCH : 0; 01728 }
| static int clear_events_cb | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 617 of file res_calendar.c.
References CMP_MATCH, destroy_event(), and evententry::event.
Referenced by ast_calendar_clear_events().
00618 { 00619 struct ast_calendar_event *event = user_data; 00620 00621 event = destroy_event(event); 00622 00623 return CMP_MATCH; 00624 }
| static void copy_event_data | ( | struct ast_calendar_event * | dst, | |
| struct ast_calendar_event * | src | |||
| ) | [static] |
Definition at line 878 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, evententry::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().
00879 { 00880 struct ast_calendar_attendee *attendee; 00881 00882 ast_string_field_set(dst, summary, src->summary); 00883 ast_string_field_set(dst, description, src->description); 00884 ast_string_field_set(dst, organizer, src->organizer); 00885 ast_string_field_set(dst, location, src->location); 00886 ast_string_field_set(dst, uid, src->uid); 00887 ast_string_field_set(dst, categories, src->categories); 00888 dst->priority = src->priority; 00889 dst->owner = src->owner; 00890 dst->start = src->start; 00891 dst->end = src->end; 00892 dst->alarm = src->alarm; 00893 dst->busy_state = src->busy_state; 00894 00895 /* Delete any existing attendees */ 00896 while ((attendee = AST_LIST_REMOVE_HEAD(&dst->attendees, next))) { 00897 ast_free(attendee); 00898 } 00899 00900 /* Copy over the new attendees */ 00901 while ((attendee = AST_LIST_REMOVE_HEAD(&src->attendees, next))) { 00902 AST_LIST_INSERT_TAIL(&dst->attendees, attendee, next); 00903 } 00904 }
| static struct ast_calendar_event* destroy_event | ( | struct ast_calendar_event * | event | ) | [static, read] |
Definition at line 592 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().
00593 { 00594 if (event->notify_sched > -1 && ast_sched_del(sched, event->notify_sched)) { 00595 ast_debug(3, "Notification running, can't delete sched entry\n"); 00596 } 00597 if (event->bs_start_sched > -1 && ast_sched_del(sched, event->bs_start_sched)) { 00598 ast_debug(3, "Devicestate update (start) running, can't delete sched entry\n"); 00599 } 00600 if (event->bs_end_sched > -1 && ast_sched_del(sched, event->bs_end_sched)) { 00601 ast_debug(3, "Devicestate update (end) running, can't delete sched entry\n"); 00602 } 00603 00604 /* If an event is being deleted and we've fired an event changing the status at the beginning, 00605 * but haven't hit the end event yet, go ahead and set the devicestate to the current busy status */ 00606 if (event->bs_start_sched < 0 && event->bs_end_sched >= 0) { 00607 if (!calendar_is_busy(event->owner)) { 00608 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); 00609 } else { 00610 ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); 00611 } 00612 } 00613 00614 return NULL; 00615 }
| static void* do_notify | ( | void * | data | ) | [static] |
Definition at line 706 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_cap_set(), ast_format_set(), AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_pbx_run(), AST_STATE_DOWN, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_substitute_variables(), ast_strdupa, ast_strlen_zero(), ast_verb, 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_variable::name, ast_calendar::name, ast_channel::nativeformats, ast_variable::next, 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, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::tech, ast_variable::value, ast_calendar::vars, and ast_channel::writeformat.
Referenced by calendar_event_notify().
00707 { 00708 struct ast_calendar_event *event = data; 00709 struct ast_dial *dial = NULL; 00710 struct ast_str *apptext = NULL, *tmpstr = NULL; 00711 struct ast_datastore *datastore; 00712 enum ast_dial_result res; 00713 struct ast_channel *chan = NULL; 00714 struct ast_variable *itervar; 00715 char *tech, *dest; 00716 char buf[8]; 00717 00718 tech = ast_strdupa(event->owner->notify_channel); 00719 00720 if ((dest = strchr(tech, '/'))) { 00721 *dest = '\0'; 00722 dest++; 00723 } else { 00724 ast_log(LOG_WARNING, "Channel should be in form Tech/Dest (was '%s')\n", tech); 00725 goto notify_cleanup; 00726 } 00727 00728 if (!(dial = ast_dial_create())) { 00729 ast_log(LOG_ERROR, "Could not create dial structure\n"); 00730 goto notify_cleanup; 00731 } 00732 00733 if (ast_dial_append(dial, tech, dest) < 0) { 00734 ast_log(LOG_ERROR, "Could not append channel\n"); 00735 goto notify_cleanup; 00736 } 00737 00738 ast_dial_set_global_timeout(dial, event->owner->notify_waittime); 00739 generate_random_string(buf, sizeof(buf)); 00740 00741 if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, 0, 0, 0, 0, 0, 0, 0, "Calendar/%s-%s", event->owner->name, buf))) { 00742 ast_log(LOG_ERROR, "Could not allocate notification channel\n"); 00743 goto notify_cleanup; 00744 } 00745 00746 chan->tech = &null_tech; 00747 ast_format_set(&chan->writeformat, AST_FORMAT_SLINEAR, 0); 00748 ast_format_set(&chan->readformat, AST_FORMAT_SLINEAR, 0); 00749 ast_format_set(&chan->rawwriteformat, AST_FORMAT_SLINEAR, 0); 00750 ast_format_set(&chan->rawreadformat, AST_FORMAT_SLINEAR, 0); 00751 /* clear native formats and set to slinear. write format is signlear so just use that to set it */ 00752 ast_format_cap_set(chan->nativeformats, &chan->writeformat); 00753 00754 if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) { 00755 ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n"); 00756 goto notify_cleanup; 00757 } 00758 00759 datastore->data = event; 00760 datastore->inheritance = DATASTORE_INHERIT_FOREVER; 00761 00762 ao2_ref(event, +1); 00763 res = ast_channel_datastore_add(chan, datastore); 00764 00765 if (!(tmpstr = ast_str_create(32))) { 00766 goto notify_cleanup; 00767 } 00768 00769 for (itervar = event->owner->vars; itervar; itervar = itervar->next) { 00770 ast_str_substitute_variables(&tmpstr, 0, chan, itervar->value); 00771 pbx_builtin_setvar_helper(chan, itervar->name, tmpstr->str); 00772 } 00773 00774 if (!(apptext = ast_str_create(32))) { 00775 goto notify_cleanup; 00776 } 00777 00778 if (!ast_strlen_zero(event->owner->notify_app)) { 00779 ast_str_set(&apptext, 0, "%s,%s", event->owner->notify_app, event->owner->notify_appdata); 00780 ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, ast_str_buffer(apptext)); 00781 } else { 00782 } 00783 00784 ast_verb(3, "Dialing %s for notification on calendar %s\n", event->owner->notify_channel, event->owner->name); 00785 res = ast_dial_run(dial, chan, 0); 00786 00787 if (res != AST_DIAL_RESULT_ANSWERED) { 00788 ast_verb(3, "Notification call for %s was not completed\n", event->owner->name); 00789 } else { 00790 struct ast_channel *answered; 00791 00792 answered = ast_dial_answered_steal(dial); 00793 if (ast_strlen_zero(event->owner->notify_app)) { 00794 ast_copy_string(answered->context, event->owner->notify_context, sizeof(answered->context)); 00795 ast_copy_string(answered->exten, event->owner->notify_extension, sizeof(answered->exten)); 00796 answered->priority = 1; 00797 ast_pbx_run(answered); 00798 } 00799 } 00800 00801 notify_cleanup: 00802 if (apptext) { 00803 ast_free(apptext); 00804 } 00805 if (tmpstr) { 00806 ast_free(tmpstr); 00807 } 00808 if (dial) { 00809 ast_dial_destroy(dial); 00810 } 00811 if (chan) { 00812 ast_channel_release(chan); 00813 } 00814 00815 event = ast_calendar_unref_event(event); 00816 00817 return NULL; 00818 }
| static void* do_refresh | ( | void * | data | ) | [static] |
Definition at line 1756 of file res_calendar.c.
References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), and ast_tvnow().
01757 { 01758 for (;;) { 01759 struct timeval now = ast_tvnow(); 01760 struct timespec ts = {0,}; 01761 int wait; 01762 01763 ast_mutex_lock(&refreshlock); 01764 01765 while (!module_unloading) { 01766 if ((wait = ast_sched_wait(sched)) < 0) { 01767 wait = 1000; 01768 } 01769 01770 ts.tv_sec = (now.tv_sec + wait / 1000) + 1; 01771 if (ast_cond_timedwait(&refresh_condition, &refreshlock, &ts) == ETIMEDOUT) { 01772 break; 01773 } 01774 } 01775 ast_mutex_unlock(&refreshlock); 01776 01777 if (module_unloading) { 01778 break; 01779 } 01780 ast_sched_runq(sched); 01781 } 01782 01783 return NULL; 01784 }
| static char* epoch_to_string | ( | char * | buf, | |
| size_t | buflen, | |||
| time_t | epoch | |||
| ) | [static] |
Definition at line 1533 of file res_calendar.c.
References ast_localtime(), and ast_strftime().
Referenced by handle_show_calendar().
01534 { 01535 struct ast_tm tm; 01536 struct timeval tv = { 01537 .tv_sec = epoch, 01538 }; 01539 01540 if (!epoch) { 01541 *buf = '\0'; 01542 return buf; 01543 } 01544 ast_localtime(&tv, &tm, NULL); 01545 ast_strftime(buf, buflen, "%F %r %z", &tm); 01546 01547 return buf; 01548 }
| static int event_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 298 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().
00299 { 00300 const struct ast_calendar_event *one = obj, *two = arg; 00301 return !strcmp(one->uid, two->uid) ? CMP_MATCH | CMP_STOP : 0; 00302 }
| static int event_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 292 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().
00293 { 00294 const struct ast_calendar_event *event = obj; 00295 return ast_str_hash(event->uid); 00296 }
| static void event_notification_destroy | ( | void * | data | ) | [static] |
Definition at line 660 of file res_calendar.c.
References ast_calendar_unref_event(), and evententry::event.
00661 { 00662 struct ast_calendar_event *event = data; 00663 00664 event = ast_calendar_unref_event(event); 00665 00666 }
| static void * event_notification_duplicate | ( | void * | data | ) | [static] |
Definition at line 668 of file res_calendar.c.
References ao2_ref, and evententry::event.
00669 { 00670 struct ast_calendar_event *event = data; 00671 00672 if (!event) { 00673 return NULL; 00674 } 00675 00676 ao2_ref(event, +1); 00677 00678 return event; 00679 }
| static void eventlist_destroy | ( | void * | data | ) | [static] |
| static void eventlist_destructor | ( | void * | obj | ) | [static] |
Definition at line 341 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().
00342 { 00343 struct eventlist *events = obj; 00344 struct evententry *entry; 00345 00346 while ((entry = AST_LIST_REMOVE_HEAD(events, list))) { 00347 ao2_ref(entry->event, -1); 00348 ast_free(entry); 00349 } 00350 }
| static void * eventlist_duplicate | ( | void * | data | ) | [static] |
| static struct ast_calendar* find_calendar | ( | const char * | name | ) | [static, read] |
Definition at line 284 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().
00285 { 00286 struct ast_calendar tmp = { 00287 .name = name, 00288 }; 00289 return ao2_find(calendars, &tmp, OBJ_POINTER); 00290 }
| static struct ast_calendar_event* find_event | ( | struct ao2_container * | events, | |
| const char * | uid | |||
| ) | [static, read] |
Definition at line 304 of file res_calendar.c.
References ao2_find, OBJ_POINTER, and ast_calendar_event::uid.
Referenced by merge_events_cb().
00305 { 00306 struct ast_calendar_event tmp = { 00307 .uid = uid, 00308 }; 00309 return ao2_find(events, &tmp, OBJ_POINTER); 00310 }
| static char* generate_random_string | ( | char * | buf, | |
| size_t | size | |||
| ) | [static] |
Generate 32 byte random string (stolen from chan_sip.c).
Definition at line 682 of file res_calendar.c.
References ast_random().
00683 { 00684 long val[4]; 00685 int x; 00686 00687 for (x = 0; x < 4; x++) { 00688 val[x] = ast_random(); 00689 } 00690 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 00691 00692 return buf; 00693 }
| static char* handle_dump_sched | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1630 of file res_calendar.c.
References ast_sched_dump(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
01631 { 01632 switch(cmd) { 01633 case CLI_INIT: 01634 e->command = "calendar dump sched"; 01635 e->usage = 01636 "Usage: calendar dump sched\n" 01637 " Dump the calendar sched context"; 01638 return NULL; 01639 01640 case CLI_GENERATE: 01641 return NULL; 01642 } 01643 01644 ast_sched_dump(sched); 01645 01646 return CLI_SUCCESS; 01647 }
| static char* handle_show_calendar | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1550 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(), 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_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.
01551 { 01552 #define FORMAT "%-17.17s : %-20.20s\n" 01553 #define FORMAT2 "%-12.12s: %-40.60s\n" 01554 struct ao2_iterator i; 01555 struct ast_calendar *cal; 01556 struct ast_calendar_event *event; 01557 int which = 0; 01558 char *ret = NULL; 01559 01560 switch(cmd) { 01561 case CLI_INIT: 01562 e->command = "calendar show calendar"; 01563 e->usage = 01564 "Usage: calendar show calendar <calendar name>\n" 01565 " Displays information about a calendar\n"; 01566 return NULL; 01567 01568 case CLI_GENERATE: 01569 if (a->pos != 3) { 01570 return NULL; 01571 } 01572 i = ao2_iterator_init(calendars, 0); 01573 while ((cal = ao2_iterator_next(&i))) { 01574 if (!strncasecmp(a->word, cal->name, strlen(a->word)) && ++which > a->n) { 01575 ret = ast_strdup(cal->name); 01576 cal = unref_calendar(cal); 01577 break; 01578 } 01579 cal = unref_calendar(cal); 01580 } 01581 ao2_iterator_destroy(&i); 01582 return ret; 01583 } 01584 01585 if (a->argc != 4) { 01586 return CLI_SHOWUSAGE; 01587 } 01588 01589 if (!(cal = find_calendar(a->argv[3]))) { 01590 return NULL; 01591 } 01592 01593 ast_cli(a->fd, FORMAT, "Name", cal->name); 01594 ast_cli(a->fd, FORMAT, "Notify channel", cal->notify_channel); 01595 ast_cli(a->fd, FORMAT, "Notify context", cal->notify_context); 01596 ast_cli(a->fd, FORMAT, "Notify extension", cal->notify_extension); 01597 ast_cli(a->fd, FORMAT, "Notify application", cal->notify_app); 01598 ast_cli(a->fd, FORMAT, "Notify appdata", cal->notify_appdata); 01599 ast_cli(a->fd, "%-17.17s : %d\n", "Refresh time", cal->refresh); 01600 ast_cli(a->fd, "%-17.17s : %d\n", "Timeframe", cal->timeframe); 01601 ast_cli(a->fd, "%-17.17s : %d\n", "Autoreminder", cal->autoreminder); 01602 ast_cli(a->fd, "%s\n", "Events"); 01603 ast_cli(a->fd, "%s\n", "------"); 01604 01605 i = ao2_iterator_init(cal->events, 0); 01606 while ((event = ao2_iterator_next(&i))) { 01607 char buf[100]; 01608 01609 ast_cli(a->fd, FORMAT2, "Summary", event->summary); 01610 ast_cli(a->fd, FORMAT2, "Description", event->description); 01611 ast_cli(a->fd, FORMAT2, "Organizer", event->organizer); 01612 ast_cli(a->fd, FORMAT2, "Location", event->location); 01613 ast_cli(a->fd, FORMAT2, "Categories", event->categories); 01614 ast_cli(a->fd, "%-12.12s: %d\n", "Priority", event->priority); 01615 ast_cli(a->fd, FORMAT2, "UID", event->uid); 01616 ast_cli(a->fd, FORMAT2, "Start", epoch_to_string(buf, sizeof(buf), event->start)); 01617 ast_cli(a->fd, FORMAT2, "End", epoch_to_string(buf, sizeof(buf), event->end)); 01618 ast_cli(a->fd, FORMAT2, "Alarm", epoch_to_string(buf, sizeof(buf), event->alarm)); 01619 ast_cli(a->fd, "\n"); 01620 01621 event = ast_calendar_unref_event(event); 01622 } 01623 ao2_iterator_destroy(&i); 01624 cal = unref_calendar(cal); 01625 return CLI_SUCCESS; 01626 #undef FORMAT 01627 #undef FORMAT2 01628 }
| 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 1474 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.
01475 { 01476 #define FORMAT "%-20.20s %-10.10s %-6.6s\n" 01477 struct ao2_iterator i; 01478 struct ast_calendar *cal; 01479 01480 switch(cmd) { 01481 case CLI_INIT: 01482 e->command = "calendar show calendars"; 01483 e->usage = 01484 "Usage: calendar show calendars\n" 01485 " Lists all registered calendars.\n"; 01486 return NULL; 01487 case CLI_GENERATE: 01488 return NULL; 01489 } 01490 01491 ast_cli(a->fd, FORMAT, "Calendar", "Type", "Status"); 01492 ast_cli(a->fd, FORMAT, "--------", "----", "------"); 01493 i = ao2_iterator_init(calendars, 0); 01494 while ((cal = ao2_iterator_next(&i))) { 01495 ast_cli(a->fd, FORMAT, cal->name, cal->tech->type, calendar_is_busy(cal) ? "busy" : "free"); 01496 cal = unref_calendar(cal); 01497 } 01498 ao2_iterator_destroy(&i); 01499 01500 return CLI_SUCCESS; 01501 #undef FORMAT 01502 }
| static char* handle_show_calendars_types | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI command to list of all calendars types currently loaded on the backend.
Definition at line 1505 of file res_calendar.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_calendar_tech::description, ast_cli_args::fd, FORMAT, evententry::list, ast_calendar_tech::type, and ast_cli_entry::usage.
01506 { 01507 #define FORMAT "%-10.10s %-30.30s\n" 01508 struct ast_calendar_tech *iter; 01509 01510 01511 switch(cmd) { 01512 case CLI_INIT: 01513 e->command = "calendar show types"; 01514 e->usage = 01515 "Usage: calendar show types\n" 01516 " Lists all registered calendars types.\n"; 01517 return NULL; 01518 case CLI_GENERATE: 01519 return NULL; 01520 } 01521 01522 ast_cli(a->fd, FORMAT, "Type", "Description"); 01523 AST_LIST_LOCK(&techs); 01524 AST_LIST_TRAVERSE(&techs, iter, list) { 01525 ast_cli(a->fd, FORMAT, iter->type, iter->description); 01526 } 01527 AST_LIST_UNLOCK(&techs); 01528 01529 return CLI_SUCCESS; 01530 #undef FORMAT 01531 }
| static int load_config | ( | int | reload | ) | [static] |
Definition at line 1017 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.
01018 { 01019 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01020 struct ast_config *tmpcfg; 01021 01022 if (!(tmpcfg = ast_config_load2("calendar.conf", "calendar", config_flags)) || 01023 tmpcfg == CONFIG_STATUS_FILEINVALID) { 01024 ast_log(LOG_ERROR, "Unable to load config calendar.conf\n"); 01025 return -1; 01026 } 01027 01028 if (tmpcfg == CONFIG_STATUS_FILEUNCHANGED) { 01029 return 0; 01030 } 01031 01032 ast_rwlock_wrlock(&config_lock); 01033 if (calendar_config) { 01034 ast_config_destroy(calendar_config); 01035 } 01036 01037 calendar_config = tmpcfg; 01038 ast_rwlock_unlock(&config_lock); 01039 01040 return 0; 01041 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1821 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, ast_sched_context_create(), 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(), and LOG_ERROR.
01822 { 01823 if (!(calendars = ao2_container_alloc(CALENDAR_BUCKETS, calendar_hash_fn, calendar_cmp_fn))) { 01824 ast_log(LOG_ERROR, "Unable to allocate calendars container!\n"); 01825 return AST_MODULE_LOAD_FAILURE; 01826 } 01827 01828 if (load_config(0)) { 01829 /* We don't have calendar support enabled */ 01830 return AST_MODULE_LOAD_DECLINE; 01831 } 01832 01833 ast_mutex_init(&refreshlock); 01834 ast_cond_init(&refresh_condition, NULL); 01835 ast_mutex_init(&reloadlock); 01836 01837 if (!(sched = ast_sched_context_create())) { 01838 ast_log(LOG_ERROR, "Unable to create sched context\n"); 01839 return AST_MODULE_LOAD_FAILURE; 01840 } 01841 01842 if (ast_pthread_create_background(&refresh_thread, NULL, do_refresh, NULL) < 0) { 01843 ast_log(LOG_ERROR, "Unable to start refresh thread--notifications disabled!\n"); 01844 } 01845 01846 ast_custom_function_register(&calendar_busy_function); 01847 ast_custom_function_register(&calendar_event_function); 01848 ast_custom_function_register(&calendar_query_function); 01849 ast_custom_function_register(&calendar_query_result_function); 01850 ast_custom_function_register(&calendar_write_function); 01851 ast_cli_register_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01852 01853 ast_devstate_prov_add("Calendar", calendarstate); 01854 01855 return AST_MODULE_LOAD_SUCCESS; 01856 }
| static int load_tech_calendars | ( | struct ast_calendar_tech * | tech | ) | [static] |
Definition at line 486 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().
00487 { 00488 struct ast_calendar *cal; 00489 const char *cat = NULL; 00490 const char *val; 00491 00492 if (!calendar_config) { 00493 ast_log(LOG_WARNING, "Calendar support disabled, not loading %s calendar module\n", tech->type); 00494 return -1; 00495 } 00496 00497 ast_rwlock_wrlock(&config_lock); 00498 while ((cat = ast_category_browse(calendar_config, cat))) { 00499 if (!strcasecmp(cat, "general")) { 00500 continue; 00501 } 00502 00503 if (!(val = ast_variable_retrieve(calendar_config, cat, "type")) || strcasecmp(val, tech->type)) { 00504 continue; 00505 } 00506 00507 /* A serious error occurred loading calendars from this tech and it should be disabled */ 00508 if (!(cal = build_calendar(calendar_config, cat, tech))) { 00509 ast_calendar_unregister(tech); 00510 ast_rwlock_unlock(&config_lock); 00511 return -1; 00512 } 00513 00514 cal = unref_calendar(cal); 00515 } 00516 00517 ast_rwlock_unlock(&config_lock); 00518 00519 return 0; 00520 }
| static int match_caltech_cb | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 542 of file res_calendar.c.
References CMP_MATCH, and ast_calendar::tech.
Referenced by ast_calendar_unregister().
00543 { 00544 struct ast_calendar *cal = user_data; 00545 struct ast_calendar_tech *tech = arg; 00546 00547 if (cal->tech == tech) { 00548 return CMP_MATCH; 00549 } 00550 00551 return 0; 00552 }
| static int merge_events_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 968 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().
00969 { 00970 struct ast_calendar_event *old_event = obj, *new_event; 00971 struct ao2_container *new_events = arg; 00972 00973 /* If we don't find the old_event in new_events, then we can safely delete the old_event */ 00974 if (!(new_event = find_event(new_events, old_event->uid))) { 00975 old_event = destroy_event(old_event); 00976 return CMP_MATCH; 00977 } 00978 00979 /* We have events to merge. If any data that will affect a scheduler event has changed, 00980 * then we need to replace the scheduler event */ 00981 schedule_calendar_event(old_event->owner, old_event, new_event); 00982 00983 /* Since we don't want to mess with cancelling sched events and adding new ones, just 00984 * copy the internals of the new_event to the old_event */ 00985 copy_event_data(old_event, new_event); 00986 00987 /* Now we can go ahead and unlink the new_event from new_events and unref it so that only completely 00988 * new events remain in the container */ 00989 ao2_unlink(new_events, new_event); 00990 new_event = ast_calendar_unref_event(new_event); 00991 00992 return 0; 00993 }
| static int null_chan_write | ( | struct ast_channel * | chan, | |
| struct ast_frame * | frame | |||
| ) | [static] |
| static int reload | ( | void | ) | [static] |
Definition at line 1730 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.
01731 { 01732 struct ast_calendar_tech *iter; 01733 01734 ast_mutex_lock(&reloadlock); 01735 01736 /* Mark existing calendars for deletion */ 01737 ao2_callback(calendars, OBJ_NODATA | OBJ_MULTIPLE, cb_pending_deletion, NULL); 01738 load_config(1); 01739 01740 AST_LIST_LOCK(&techs); 01741 AST_LIST_TRAVERSE(&techs, iter, list) { 01742 if (load_tech_calendars(iter)) { 01743 ast_log(LOG_WARNING, "Failed to reload %s calendars, module disabled\n", iter->type); 01744 } 01745 } 01746 AST_LIST_UNLOCK(&techs); 01747 01748 /* Delete calendars that no longer show up in the config */ 01749 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, cb_rm_pending_deletion, NULL); 01750 01751 ast_mutex_unlock(&reloadlock); 01752 01753 return 0; 01754 }
| 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 906 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().
00907 { 00908 struct timeval now = ast_tvnow(); 00909 struct ast_calendar_event *event; 00910 time_t alarm_notify_sched = 0, devstate_sched_start, devstate_sched_end; 00911 int changed = 0; 00912 00913 event = cmp_event ? cmp_event : old_event; 00914 00915 ao2_lock(event); 00916 if (!cmp_event || old_event->alarm != event->alarm) { 00917 changed = 1; 00918 if (cal->autoreminder) { 00919 alarm_notify_sched = (event->start - (60 * cal->autoreminder) - now.tv_sec) * 1000; 00920 } else if (event->alarm) { 00921 alarm_notify_sched = (event->alarm - now.tv_sec) * 1000; 00922 } 00923 00924 /* For now, send the notification if we missed it, but the meeting hasn't happened yet */ 00925 if (event->start >= now.tv_sec) { 00926 if (alarm_notify_sched <= 0) { 00927 alarm_notify_sched = 1; 00928 } 00929 ast_mutex_lock(&refreshlock); 00930 AST_SCHED_REPLACE(old_event->notify_sched, sched, alarm_notify_sched, calendar_event_notify, old_event); 00931 ast_mutex_unlock(&refreshlock); 00932 ast_debug(3, "Calendar alarm event notification scheduled to happen in %ld ms\n", (long) alarm_notify_sched); 00933 } 00934 } 00935 00936 if (!cmp_event || old_event->start != event->start) { 00937 changed = 1; 00938 devstate_sched_start = (event->start - now.tv_sec) * 1000; 00939 00940 if (devstate_sched_start < 1) { 00941 devstate_sched_start = 1; 00942 } 00943 00944 ast_mutex_lock(&refreshlock); 00945 AST_SCHED_REPLACE(old_event->bs_start_sched, sched, devstate_sched_start, calendar_devstate_change, old_event); 00946 ast_mutex_unlock(&refreshlock); 00947 ast_debug(3, "Calendar bs_start event notification scheduled to happen in %ld ms\n", (long) devstate_sched_start); 00948 } 00949 00950 if (!cmp_event || old_event->end != event->end) { 00951 changed = 1; 00952 devstate_sched_end = (event->end - now.tv_sec) * 1000; 00953 ast_mutex_lock(&refreshlock); 00954 AST_SCHED_REPLACE(old_event->bs_end_sched, sched, devstate_sched_end, calendar_devstate_change, old_event); 00955 ast_mutex_unlock(&refreshlock); 00956 ast_debug(3, "Calendar bs_end event notification scheduled to happen in %ld ms\n", (long) devstate_sched_end); 00957 } 00958 00959 if (changed) { 00960 ast_cond_signal(&refresh_condition); 00961 } 00962 00963 ao2_unlock(event); 00964 00965 return 0; 00966 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1787 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, evententry::list, ast_calendar_tech::module, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.
01788 { 01789 struct ast_calendar_tech *tech; 01790 01791 ast_devstate_prov_del("calendar"); 01792 ast_custom_function_unregister(&calendar_busy_function); 01793 ast_custom_function_unregister(&calendar_event_function); 01794 ast_custom_function_unregister(&calendar_query_function); 01795 ast_custom_function_unregister(&calendar_query_result_function); 01796 ast_custom_function_unregister(&calendar_write_function); 01797 ast_cli_unregister_multiple(calendar_cli, ARRAY_LEN(calendar_cli)); 01798 01799 /* Remove all calendars */ 01800 ao2_callback(calendars, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL); 01801 01802 ast_mutex_lock(&refreshlock); 01803 module_unloading = 1; 01804 ast_cond_signal(&refresh_condition); 01805 ast_mutex_unlock(&refreshlock); 01806 pthread_join(refresh_thread, NULL); 01807 01808 AST_LIST_LOCK(&techs); 01809 AST_LIST_TRAVERSE_SAFE_BEGIN(&techs, tech, list) { 01810 ast_unload_resource(tech->module, 0); 01811 } 01812 AST_LIST_TRAVERSE_SAFE_END; 01813 AST_LIST_UNLOCK(&techs); 01814 01815 ast_config_destroy(calendar_config); 01816 calendar_config = NULL; 01817 01818 return 0; 01819 }
| static struct ast_calendar* unref_calendar | ( | struct ast_calendar * | cal | ) | [static, read] |
Definition at line 266 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().
00267 { 00268 ao2_ref(cal, -1); 00269 return NULL; 00270 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static] |
Definition at line 1862 of file res_calendar.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1862 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 1065 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ast_cli_entry calendar_cli[] [static] |
struct ast_config* calendar_config [static] |
Definition at line 246 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 1709 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 1245 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 1356 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 1468 of file res_calendar.c.
Referenced by load_module(), and unload_module().
struct ao2_container* calendars [static] |
Definition at line 213 of file res_calendar.c.
ast_rwlock_t config_lock = { {0} , NULL, 1 } [static] |
Definition at line 247 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 226 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 232 of file res_calendar.c.
int module_unloading [static] |
Definition at line 219 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 700 of file res_calendar.c.
ast_cond_t refresh_condition [static] |
Definition at line 217 of file res_calendar.c.
pthread_t refresh_thread = AST_PTHREADT_NULL [static] |
Definition at line 215 of file res_calendar.c.
ast_mutex_t refreshlock [static] |
Definition at line 216 of file res_calendar.c.
Referenced by caldav_load_calendar(), ewscal_load_calendar(), exchangecal_load_calendar(), and ical_load_calendar().
ast_mutex_t reloadlock [static] |
Definition at line 218 of file res_calendar.c.
struct ast_sched_context* sched [static] |
Definition at line 214 of file res_calendar.c.
1.5.6