Version 0.3.0 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@566 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 23 years ago
parent 12a42fbf3a
commit 3d1d4221aa

@ -1,7 +1,7 @@
/* /*
* Asterisk -- A telephony toolkit for Linux. * Asterisk -- A telephony toolkit for Linux.
* *
* True call queues * True call queues with optional send URL on answer
* *
* Copyright (C) 1999, Mark Spencer * Copyright (C) 1999, Mark Spencer
* *
@ -23,6 +23,7 @@
#include <asterisk/parking.h> #include <asterisk/parking.h>
#include <asterisk/musiconhold.h> #include <asterisk/musiconhold.h>
#include <asterisk/cli.h> #include <asterisk/cli.h>
#include <asterisk/manager.h> /* JDG */
#include <asterisk/config.h> #include <asterisk/config.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
@ -47,7 +48,7 @@ static char *app = "Queue";
static char *synopsis = "Queue a call for a call queue"; static char *synopsis = "Queue a call for a call queue";
static char *descrip = static char *descrip =
" Queue(queuename[|timeout[|options]]):\n" " Queue(queuename[|options[|URL][|announceoverride]]):\n"
"Queues an incoming call in a particular call queue as defined in queues.conf.\n" "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
" This application returns -1 if the originating channel hangs up, or if the\n" " This application returns -1 if the originating channel hangs up, or if the\n"
"call is bridged and either of the parties in the bridge terminate the call.\n" "call is bridged and either of the parties in the bridge terminate the call.\n"
@ -58,7 +59,9 @@ static char *descrip =
" 'd' -- data-quality (modem) call (minimum delay).\n" " 'd' -- data-quality (modem) call (minimum delay).\n"
" 'H' -- allow caller to hang up by hitting *.\n" " 'H' -- allow caller to hang up by hitting *.\n"
" In addition to transferring the call, a call may be parked and then picked\n" " In addition to transferring the call, a call may be parked and then picked\n"
"up by another user.\n"; "up by another user.\n"
" The optionnal URL will be sent to the called party if the channel supports\n"
"it.\n";
/* We define a customer "local user" structure because we /* We define a customer "local user" structure because we
use it not only for keeping track of what is in use but use it not only for keeping track of what is in use but
@ -81,7 +84,7 @@ struct queue_ent {
struct ast_call_queue *parent; /* What queue is our parent */ struct ast_call_queue *parent; /* What queue is our parent */
char moh[80]; /* Name of musiconhold to be used */ char moh[80]; /* Name of musiconhold to be used */
char announce[80]; /* Announcement to play */ char announce[80]; /* Announcement to play */
char context[80]; /* Announcement to play */ char context[80]; /* Context when user exits queue */
int pos; /* Where we are in the queue */ int pos; /* Where we are in the queue */
time_t start; /* When we started holding */ time_t start; /* When we started holding */
struct ast_channel *chan; /* Our channel */ struct ast_channel *chan; /* Our channel */
@ -152,6 +155,9 @@ static int join_queue(char *queuename, struct queue_ent *qe)
strncpy(qe->context, q->context, sizeof(qe->context)); strncpy(qe->context, q->context, sizeof(qe->context));
q->count++; q->count++;
res = 0; res = 0;
manager_event(EVENT_FLAG_CALL, "Join",
"Queue: %s\r\nPosition: %d\r\n", q->name, qe->pos );
} }
ast_pthread_mutex_unlock(&q->lock); ast_pthread_mutex_unlock(&q->lock);
break; break;
@ -205,6 +211,8 @@ static void leave_queue(struct queue_ent *qe)
return; return;
ast_pthread_mutex_lock(&q->lock); ast_pthread_mutex_lock(&q->lock);
/* Take us out of the queue */ /* Take us out of the queue */
manager_event(EVENT_FLAG_CALL, "Leave",
"Queue: %s\r\n", q->name );
prev = NULL; prev = NULL;
cur = q->head; cur = q->head;
while(cur) { while(cur) {
@ -397,7 +405,7 @@ static int wait_our_turn(struct queue_ent *qe)
return res; return res;
} }
static int try_calling(struct queue_ent *qe, char *options) static int try_calling(struct queue_ent *qe, char *options, char *announceoverride, char *url)
{ {
struct member *cur; struct member *cur;
struct localuser *outgoing=NULL, *tmp = NULL; struct localuser *outgoing=NULL, *tmp = NULL;
@ -408,10 +416,15 @@ static int try_calling(struct queue_ent *qe, char *options)
char restofit[AST_MAX_EXTENSION]; char restofit[AST_MAX_EXTENSION];
char *newnum; char *newnum;
struct ast_channel *peer; struct ast_channel *peer;
int res = 0; int res = 0, bridge = 0;
char *announce = NULL;
/* Hold the lock while we setup the outgoing calls */ /* Hold the lock while we setup the outgoing calls */
ast_pthread_mutex_lock(&qe->parent->lock); ast_pthread_mutex_lock(&qe->parent->lock);
cur = qe->parent->members; cur = qe->parent->members;
if (strlen(qe->announce))
announce = qe->announce;
if (announceoverride && strlen(announceoverride))
announce = announceoverride;
while(cur) { while(cur) {
/* Get a technology/[device:]number pair */ /* Get a technology/[device:]number pair */
tmp = malloc(sizeof(struct localuser)); tmp = malloc(sizeof(struct localuser));
@ -432,6 +445,10 @@ static int try_calling(struct queue_ent *qe, char *options)
if (strchr(options, 'H')) if (strchr(options, 'H'))
tmp->allowdisconnect = 1; tmp->allowdisconnect = 1;
} }
if (url) {
ast_log(LOG_DEBUG, "Queue with URL=%s_\n", url);
} else
ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
strncpy(numsubst, cur->loc, sizeof(numsubst)-1); strncpy(numsubst, cur->loc, sizeof(numsubst)-1);
/* If we're dialing by extension, look at the extension to know what to dial */ /* If we're dialing by extension, look at the extension to know what to dial */
@ -539,9 +556,10 @@ static int try_calling(struct queue_ent *qe, char *options)
/* Stop music on hold */ /* Stop music on hold */
ast_moh_stop(qe->chan); ast_moh_stop(qe->chan);
outgoing = NULL; outgoing = NULL;
if (strlen(qe->announce)) { if (announce) {
int res2; int res2;
res2 = ast_streamfile(peer, qe->announce, peer->language); res2 = ast_streamfile(peer, announce, peer->language);
/* XXX Need a function to wait on *both* streams XXX */
if (!res2) if (!res2)
res2 = ast_waitstream(peer, ""); res2 = ast_waitstream(peer, "");
else else
@ -575,8 +593,15 @@ static int try_calling(struct queue_ent *qe, char *options)
} }
/* Drop out of the queue at this point, to prepare for next caller */ /* Drop out of the queue at this point, to prepare for next caller */
leave_queue(qe); leave_queue(qe);
res = ast_bridge_call(qe->chan, peer, allowredir, allowdisconnect); /* JDG: sendurl */
if( url && strlen(url) && ast_channel_supports_html(peer) ) {
ast_log(LOG_DEBUG, "app_queue: sendurl=%s.\n", url);
ast_channel_sendurl( peer, url );
} /* /JDG */
bridge = ast_bridge_call(qe->chan, peer, allowredir, allowdisconnect);
ast_hangup(peer); ast_hangup(peer);
if( bridge == 0 ) res=1; /* JDG: bridge successfull, leave app_queue */
else res = bridge; /* bridge error, stay in the queue */
} }
out: out:
hanguptree(outgoing, NULL); hanguptree(outgoing, NULL);
@ -616,12 +641,14 @@ static int queue_exec(struct ast_channel *chan, void *data)
char *queuename; char *queuename;
char info[512]; char info[512];
char *options = NULL; char *options = NULL;
char *url = NULL;
char *announceoverride = NULL;
/* Our queue entry */ /* Our queue entry */
struct queue_ent qe; struct queue_ent qe;
if (!data) { if (!data) {
ast_log(LOG_WARNING, "Queue requires an argument (queuename|optional timeout)\n"); ast_log(LOG_WARNING, "Queue requires an argument (queuename|optional timeout|optional URL)\n");
return -1; return -1;
} }
@ -635,9 +662,20 @@ static int queue_exec(struct ast_channel *chan, void *data)
if (options) { if (options) {
*options = '\0'; *options = '\0';
options++; options++;
url = strchr(options, '|');
if (url) {
*url = '\0';
url++;
announceoverride = strchr(url, '|');
if (announceoverride) {
*announceoverride = '\0';
announceoverride++;
} }
} }
}
}
printf("queue: %s, options: %s, url: %s, announce: %s\n",
queuename, options, url, announceoverride);
/* Setup our queue entry */ /* Setup our queue entry */
memset(&qe, 0, sizeof(qe)); memset(&qe, 0, sizeof(qe));
qe.chan = chan; qe.chan = chan;
@ -662,7 +700,7 @@ static int queue_exec(struct ast_channel *chan, void *data)
} }
if (!res) { if (!res) {
for (;;) { for (;;) {
res = try_calling(&qe, options); res = try_calling(&qe, options, announceoverride, url);
if (res) if (res)
break; break;
res = wait_a_bit(&qe); res = wait_a_bit(&qe);
@ -864,6 +902,13 @@ static int queues_show(int fd, int argc, char **argv)
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
/* JDG: callback to display queues status in manager */
static int manager_queues_show( struct mansession *s, struct message *m )
{
char *a[] = { "show", "queues" };
return queues_show( s->fd, 2, a );
} /* /JDG */
static char show_queues_usage[] = static char show_queues_usage[] =
"Usage: show queues\n" "Usage: show queues\n"
" Provides summary information on call queues.\n"; " Provides summary information on call queues.\n";
@ -872,12 +917,11 @@ static struct ast_cli_entry cli_show_queues = {
{ "show", "queues", NULL }, queues_show, { "show", "queues", NULL }, queues_show,
"Show status of queues", show_queues_usage, NULL }; "Show status of queues", show_queues_usage, NULL };
int unload_module(void) int unload_module(void)
{ {
STANDARD_HANGUP_LOCALUSERS; STANDARD_HANGUP_LOCALUSERS;
ast_cli_unregister(&cli_show_queues); ast_cli_unregister(&cli_show_queues);
ast_manager_unregister( "Queues" );
return ast_unregister_application(app); return ast_unregister_application(app);
} }
@ -885,8 +929,10 @@ int load_module(void)
{ {
int res; int res;
res = ast_register_application(app, queue_exec, synopsis, descrip); res = ast_register_application(app, queue_exec, synopsis, descrip);
if (!res) if (!res) {
ast_cli_register(&cli_show_queues); ast_cli_register(&cli_show_queues);
ast_manager_register( "Queues", 0, manager_queues_show, "Queues" );
}
reload_queues(); reload_queues();
return res; return res;
} }

@ -18,6 +18,10 @@
#define _ASTERISK_MANAGER_H #define _ASTERISK_MANAGER_H
#include <stdarg.h> #include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* /*
* Call management packages are text fields of the form a: b. There is * Call management packages are text fields of the form a: b. There is
@ -42,6 +46,46 @@
#define EVENT_FLAG_COMMAND (1 << 4) /* Ability to read/set commands */ #define EVENT_FLAG_COMMAND (1 << 4) /* Ability to read/set commands */
#define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */ #define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */
/* JDG: export manager structures */
#define MAX_HEADERS 80
#define MAX_LEN 256
struct mansession {
pthread_t t;
pthread_mutex_t lock;
struct sockaddr_in sin;
int fd;
int blocking;
char username[80];
int authenticated;
int readperm;
int writeperm;
char inbuf[MAX_LEN];
int inlen;
struct mansession *next;
};
struct message {
int hdrcount;
char headers[MAX_HEADERS][MAX_LEN];
};
struct manager_action {
char action[256];
char *synopsis;
int authority;
int (*func)(struct mansession *s, struct message *m);
struct manager_action *next;
};
/* External routines may register/unregister manager callbacks this way */
int ast_manager_register( char *action, int authority,
int (*func)(struct mansession *s, struct message *m), char *synopsis);
int ast_manager_unregister( char *action );
/* /JDG */
/* External routines may send asterisk manager events this way */ /* External routines may send asterisk manager events this way */
extern int manager_event(int category, char *event, char *contents, ...) extern int manager_event(int category, char *event, char *contents, ...)
__attribute__ ((format (printf, 3,4))); __attribute__ ((format (printf, 3,4)));

Loading…
Cancel
Save