dect
/
asterisk
Archived
13
0
Fork 0

Add Archive option to call files and add documentation on them. (issue #5426 reported by ezio - props to blitzrage for proof reading the documentation)

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@30299 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
file 2006-05-25 17:58:55 +00:00
parent 861939a243
commit be0f7def4c
3 changed files with 209 additions and 13 deletions

139
doc/callfiles.txt Normal file
View File

@ -0,0 +1,139 @@
Asterisk call files
===================
Asterisk has the ability to initiate a call from outside of the normal
methods such as the dialplan, manager interface, or spooling interface.
Using the call file method, you must give Asterisk the following information:
* How to perform the call, similar to the Dial() application
* What to do when the call is answered
With call files you submit this information simply by creating a file with
the required syntax and placing it in the outgoing spooling directory, located
by default in /var/spool/asterisk/outgoing/ (configurable in asterisk.conf).
The pbx_spool module aggressively examines the directory contents every second,
creating a new call for every call file it finds. Do NOT write or create
the call file directly in the outgoing directory, but always create the file
in another directory of the same filesystem and then move the file to the
/var/spool/asterisk/outgoing directory, or Asterisk may read just a partial
file.
The call file syntax
====================
The call file consists of <Key>: <value> pairs; one per line.
Comments are indicated by a '#' character that begins a line, or follows a space
or tab character. To be consistant with the configuration files in Asterisk,
comments can also be indicated by a semicolon. However, the multiline comments
(;-- --;) used in Asterisk configuration files are not supported. Semicolons can
be escaped by a backslash.
The following keys-value pairs are used to specify how setup a call:
Channel: <channel> the channel to use for the new call, in the form
technology/resource as in the Dial application. This
value is required.
Callerid: <callerid> the caller id to use.
WaitTime: <number> how many seconds to wait for an answer before the call
fails (ring cycle). Default 45 seconds.
Maxretries: <number> number of retries before failing, not including the
initial attempt. Default = 0 e.g. don't retry if fails.
RetryTime: <number> how many seconds to wait before retry. The default is
300 (5 minutes).
Account: <account> the account code for the call. This value will be
assigned to CDR(accountcode)
When the call answers there are two choices:
* Execute a single application, or
* Execute the dialplan at the specified context/extension/priority.
To execute an application:
--------------------------
Application: <appname> the application to execute
Data: <args> the application arguments
To start executing applications in the dialplan:
------------------------------------------------
Context: <context> the context in the dialplan
Extension: <exten> the extension in the specified context
Priority: <priority> the priority of the specified extension
(numeric or label)
Setvar: <var=value> you may also assign values to variables that will be
available to the channel, as if you had performed a
Set(var=value) in the dialplan. More than one Setvar:
maybe specified.
The processing of the call file ends when the call is answered and terminated; when
the call was not answered in the initial attempt and subsequent retries; or if
the call file can't be successfully read and parsed.
To specify what to do with the call file at the end of processing:
Archive: <yes|no> if "no" the call file is deleted. If set to "yes" the
call file is moved to the "outgoing_done" subdirectory
of the Asterisk spool directory. The default is to
delete the call file.
If the call file is archived, Asterisk will append to the call file:
Status: <exitstatus> can be "Expired", "Completed" or "Failed"
Other lines generated by Asterisk:
Asterisk keep track of how many retries the call has already attempted,
appending to the call file the following key-pairs in the form:
StartRetry: <pid> <retrycount> (<time>)
EndRetry: <pid> <retrycount> (<time>)
With the main process ID (pid) of the Asterisk process, the retry number, and
the attempts start and end times in time_t format.
Directory locations
===================
<astspooldir>/outgoing the outgoing dir, where call files are put
for processing
<astspooldir>/outgoing_done the archive dir
<astspooldir> is specified in asterisk.conf, usually /var/spool/asterisk
How to schedule a call
======================
Call files that have the time of the last modification in the future are ignored
by Asterisk. This makes it possible to modify the time of a call file to the
wanted time, move to the outgoing directory, and Asterisk will attempt to
create the call at that time.

View File

@ -58,10 +58,13 @@ enum {
* maximum number of retries is exceeded, even if the
* modification time of the call file is in the future.
*/
SPOOL_FLAG_ALWAYS_DELETE = (1 << 0)
SPOOL_FLAG_ALWAYS_DELETE = (1 << 0),
/* Don't unlink the call file after processing, move in qdonedir */
SPOOL_FLAG_ARCHIVE = (1 << 1)
};
static char qdir[255];
static char qdonedir[255];
struct outgoing {
char fn[256];
@ -228,6 +231,8 @@ static int apply_outgoing(struct outgoing *o, char *fn, FILE *f)
ast_copy_string(o->account, c, sizeof(o->account));
} else if (!strcasecmp(buf, "alwaysdelete")) {
ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE);
} else if (!strcasecmp(buf, "archive")) {
ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE);
} else {
ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
}
@ -264,17 +269,59 @@ static void safe_append(struct outgoing *o, time_t now, char *s)
}
}
static void check_unlink(struct outgoing *o)
/*!
* \brief Remove a call file from the outgoing queue optionally moving it in the archive dir
*
* \param o the pointer to outgoing struct
* \param status the exit status of the call. Can be "Completed", "Failed" or "Expired"
*/
static int remove_from_queue(struct outgoing *o, const char *status)
{
if (ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE))
unlink(o->fn);
else {
int fd;
FILE *f;
char newfn[256];
const char *bname;
if (!ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE)) {
struct stat current_file_status;
if (!stat(o->fn, &current_file_status))
if (time(NULL) >= current_file_status.st_mtime)
unlink(o->fn);
if (time(NULL) < current_file_status.st_mtime)
return 0;
}
if (!ast_test_flag(&o->options, SPOOL_FLAG_ARCHIVE)) {
unlink(o->fn);
return 0;
}
if (mkdir(qdonedir, 0700) && (errno != EEXIST)) {
ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir);
unlink(o->fn);
return -1;
}
fd = open(o->fn, O_WRONLY|O_APPEND);
if (fd > -1) {
f = fdopen(fd, "a");
if (f) {
fprintf(f, "Status: %s\n", status);
fclose(f);
} else
close(fd);
}
bname = strrchr(o->fn,'/');
if (bname == NULL)
bname = o->fn;
else
bname++;
snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname);
/* a existing call file the archive dir is overwritten */
unlink(newfn);
if (rename(o->fn, newfn) != 0) {
unlink(o->fn);
return -1;
} else
return 0;
}
static void *attempt_thread(void *data)
@ -295,7 +342,7 @@ static void *attempt_thread(void *data)
if (o->retries >= o->maxretries + 1) {
/* Max retries exceeded */
ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
check_unlink(o);
remove_from_queue(o, "Expired");
} else {
/* Notate that the call is still active */
safe_append(o, time(NULL), "EndRetry");
@ -303,7 +350,7 @@ static void *attempt_thread(void *data)
} else {
ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
check_unlink(o);
remove_from_queue(o, "Completed");
}
free_outgoing(o);
return NULL;
@ -357,19 +404,19 @@ static int scan_service(char *fn, time_t now, time_t atime)
} else {
ast_log(LOG_EVENT, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
free_outgoing(o);
unlink(fn);
remove_from_queue(o, "Expired");
return 0;
}
} else {
free_outgoing(o);
ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn);
fclose(f);
unlink(fn);
remove_from_queue(o, "Failed");
}
} else {
free_outgoing(o);
ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno));
unlink(fn);
remove_from_queue(o, "Failed");
}
} else
ast_log(LOG_WARNING, "Out of memory :(\n");
@ -445,6 +492,7 @@ static int load_module(void *mod)
ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
return 0;
}
snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done");
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if ((ret = ast_pthread_create(&thread,&attr,scan_thread, NULL)) != 0) {

View File

@ -69,3 +69,12 @@ Priority: 1
#Set: file2=/tmp/msg
#Set: timestamp=20021023104500
#Set: CDR(userfield|r)=42
#
# Setting Archive to yes the call file is never deleted, but is moved
# in the subdir "outgoing_done" of the spool directory. In this case
# will be appended a line with "Status: value", where value can be
# Completed, Expired or Failed.
#
#Archive: yes