Plane commits (a.k.a. the Delta deltas): 1) Make muted reconnect 2) Add "X" option to meetme and add ${MEETME_EXIT_CONTEXT}, 3) Allow SIP call parking with supervised transfer, 4) Only create parking entries when calls actually get parked, 5) Add "sunshine" song, 6) Update hardware documentation, 7) Don't load empty strings from history file

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3572 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 21 years ago
parent 437f625786
commit f3522b6c01

@ -1,3 +1,10 @@
-- Additional CDR backends
-- Allow muted to reconnect
-- Call parking improvements (including SIP parking support)
-- Added licensed hold music from FreePlayMusic
-- GR-303 and Zap improvements
-- More bug fixes from the bug tracker
-- Improved FreeBSD/OpenBSD/MacOS X support
Asterisk 1.0-RC1
-- Innumerable bug fixes and features from the bug tracker
-- Added Open Settlement Protocol (OSP) support

@ -16,11 +16,11 @@ Zaptel compatible hardware
* Wildcard X100P - Single FXO interface connects to Loopstart phone
line
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
* Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
interfaces. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
* Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI
(or PRA) interfaces. Supports PRA/PRI, EuroISDN voice and data.
* Wildcard T100P - Single T1 interface connects to a single T1/PRI
interface. Supports RBS and PRI voice and PPP, FR, and HDLC data.

@ -59,6 +59,9 @@ static char *descrip =
" 'm' -- set monitor only mode (Listen only, no talking)\n"
" 't' -- set talk only mode. (Talk only, no listening)\n"
" 'p' -- allow user to exit the conference by pressing '#'\n"
" 'X' -- allow user to exit the conference by entering a valid single\n"
" digit extension ${MEETME_EXIT_CONTEXT} or the current context\n"
" if that variable is not defined.\n"
" 'd' -- dynamically add conference\n"
" 'D' -- dynamically add conference, prompting for a PIN\n"
" 'e' -- select an empty conference\n"
@ -148,6 +151,7 @@ static int admin_exec(struct ast_channel *chan, void *data);
#define CONFFLAG_MOH (1 << 9) /* Set to have music on hold when user is alone in conference */
#define CONFFLAG_ADMINEXIT (1 << 10) /* If set the MeetMe will return if all marked with this flag left */
#define CONFFLAG_WAITMARKED (1 << 11) /* If set, the MeetMe will wait until a marked user enters */
#define CONFFLAG_EXIT_CONTEXT (1 << 12) /* If set, the MeetMe will wait until a marked user enters */
static int careful_write(int fd, unsigned char *data, int len)
@ -504,6 +508,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
char *agifile;
char *agifiledefault = "conf-background.agi";
char meetmesecs[30] = "";
char exitcontext[AST_MAX_EXTENSION] = "";
ZT_BUFFERINFO bi;
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
@ -560,6 +565,14 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
user->adminflags = 0;
ast_mutex_unlock(&conflock);
origquiet = confflags & CONFFLAG_QUIET;
if (confflags & CONFFLAG_EXIT_CONTEXT) {
if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT")))
strncpy(exitcontext, agifile, sizeof(exitcontext) - 1);
else if (!ast_strlen_zero(chan->macrocontext))
strncpy(exitcontext, chan->macrocontext, sizeof(exitcontext) - 1);
else
strncpy(exitcontext, chan->context, sizeof(exitcontext) - 1);
}
while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers < 0)) {
confflags &= ~CONFFLAG_QUIET;
confflags |= origquiet;
@ -806,7 +819,18 @@ zapretry:
f = ast_read(c);
if (!f)
break;
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
char tmp[2];
tmp[0] = f->subclass;
tmp[1] = '\0';
if (ast_exists_extension(chan, exitcontext, tmp, 1, chan->callerid)) {
strncpy(chan->context, exitcontext, sizeof(chan->context) - 1);
strncpy(chan->exten, tmp, sizeof(chan->exten) - 1);
chan->priority = 0;
ret = 0;
break;
}
} else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
ret = 0;
break;
} else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) {
@ -1187,6 +1211,8 @@ static int conf_exec(struct ast_channel *chan, void *data)
confflags |= CONFFLAG_MOH;
if (strchr(inflags, 'x'))
confflags |= CONFFLAG_ADMINEXIT;
if (strchr(inflags, 'X'))
confflags |= CONFFLAG_EXIT_CONTEXT;
if (strchr(inflags, 'b'))
confflags |= CONFFLAG_AGI;
if (strchr(inflags, 'w'))

@ -689,7 +689,7 @@ static int remoteconsolehandler(char *s)
{
int ret = 0;
/* Called when readline data is available */
if (s && !ast_strlen_zero(s))
if (s && !ast_all_zeros(s))
ast_el_add_history(s);
/* Give the console access to the shell */
if (s) {
@ -1341,6 +1341,8 @@ static int ast_el_read_history(char *filename)
fgets(buf, sizeof(buf), f);
if (!strcmp(buf, "_HiStOrY_V2_\n"))
continue;
if (ast_all_zeros(buf))
continue;
if ((ret = ast_el_add_history(buf)) == -1)
break;
}

@ -2808,9 +2808,9 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
}
} else {
if (p->hookstate == MGCP_OFFHOOK) {
ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
} else {
ast_log(LOG_WARNING, "On hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
}
if (sub->owner->bridge) {

@ -535,8 +535,16 @@ int main(int argc, char *argv[])
if (needfork)
daemon(0,0);
for(;;) {
if (wait_event())
if (wait_event()) {
fclose(astf);
while(connect_asterisk()) {
sleep(5);
}
if (login_asterisk()) {
fclose(astf);
exit(1);
}
}
}
exit(0);
}

12
pbx.c

@ -1,4 +1,4 @@
/*
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Core PBX routines.
@ -2044,7 +2044,7 @@ int ast_context_remove_include2(struct ast_context *con, char *include, char *re
while (i) {
/* find our include */
if (!strcmp(i->name, include) &&
(!strcmp(i->registrar, registrar) || !registrar)) {
(!registrar || !strcmp(i->registrar, registrar))) {
/* remove from list */
if (pi)
pi->next = i->next;
@ -2116,7 +2116,7 @@ int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, ch
while (i) {
/* find our switch */
if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
(!strcmp(i->registrar, registrar) || !registrar)) {
(!registrar || !strcmp(i->registrar, registrar))) {
/* remove from list */
if (pi)
pi->next = i->next;
@ -2189,7 +2189,7 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
/* look for right extension */
if (!strcmp(exten->exten, extension) &&
(!strcmp(exten->registrar, registrar) || !registrar)) {
(!registrar || !strcmp(exten->registrar, registrar))) {
struct ast_exten *peer;
/* should we free all peers in this extension? (priority == 0)? */
@ -2224,7 +2224,7 @@ int ast_context_remove_extension2(struct ast_context *con, char *extension, int
while (peer) {
/* is this our extension? */
if (peer->priority == priority &&
(!strcmp(peer->registrar, registrar) || !registrar)) {
(!registrar || !strcmp(peer->registrar, registrar) )) {
/* we are first priority extension? */
if (!previous_peer) {
/* exists previous extension here? */
@ -3459,7 +3459,7 @@ int ast_context_remove_ignorepat2(struct ast_context *con, char *ignorepat, char
ip = con->ignorepats;
while (ip) {
if (!strcmp(ip->pattern, ignorepat) &&
(registrar == ip->registrar || !registrar)) {
(!registrar || (registrar == ip->registrar))) {
if (ipl) {
ipl->next = ip->next;
free(ip);

@ -62,7 +62,7 @@ static int parking_stop = 750;
static int transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
/* Registrar for operations */
static char *registrar = "res_parking";
static char *registrar = "res_features";
static char *synopsis = "Answer a parked call";
@ -72,6 +72,18 @@ static char *descrip = "ParkedCall(exten):"
"into the dialplan, although you should include the 'parkedcalls'\n"
"context.\n";
static char *parkcall = "Park";
static char *synopsis2 = "Park yourself";
static char *descrip2 = "Park(exten):"
"Used to park yourself (typically in combination with a supervised\n"
"transfer to know the parking space. This Application is always\n"
"registered internally and does not need to be explicitly added\n"
"into the dialplan, although you should include the 'parkedcalls'\n"
"context.\n";
struct parkeduser {
struct ast_channel *chan;
struct timeval start;
@ -81,6 +93,7 @@ struct parkeduser {
char exten[AST_MAX_EXTENSION];
int priority;
int parkingtime;
int notquiteyet;
struct parkeduser *next;
};
@ -110,6 +123,8 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
after these channels too */
struct parkeduser *pu, *cur;
int x;
char exten[AST_MAX_EXTENSION];
struct ast_context *con;
pu = malloc(sizeof(struct parkeduser));
if (pu) {
ast_mutex_lock(&parking_lock);
@ -129,6 +144,7 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
pu->chan = chan;
/* Start music on hold */
if (chan != peer)
ast_moh_start(pu->chan, NULL);
gettimeofday(&pu->start, NULL);
pu->parkingnum = x;
@ -154,6 +170,9 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
pu->priority = chan->priority;
pu->next = parkinglot;
parkinglot = pu;
/* If parking a channel directly, don't quiet yet get parking running on it */
if (peer == chan)
pu->notquiteyet = 1;
ast_mutex_unlock(&parking_lock);
/* Wake up the (presumably select()ing) thread */
pthread_kill(parking_thread, SIGURG);
@ -171,8 +190,26 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
,(pu->chan->callerid ? pu->chan->callerid : "")
);
if (peer)
if (peer) {
ast_say_digits(peer, pu->parkingnum, "", peer->language);
if (pu->notquiteyet) {
/* Wake up parking thread if we're really done */
ast_moh_start(pu->chan, NULL);
pu->notquiteyet = 0;
pthread_kill(parking_thread, SIGURG);
}
}
con = ast_context_find(parking_con);
if (!con) {
con = ast_context_create(NULL,parking_con, registrar);
if (!con) {
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
}
}
if (con) {
snprintf(exten, sizeof(exten), "%d", x);
ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
}
return 0;
} else {
ast_log(LOG_WARNING, "No more parking spaces\n");
@ -441,6 +478,8 @@ static void *do_parking_thread(void *ignore)
struct parkeduser *pu, *pl, *pt = NULL;
struct timeval tv;
struct ast_frame *f;
char exten[AST_MAX_EXTENSION];
struct ast_context *con;
int x;
fd_set rfds, efds;
fd_set nrfds, nefds;
@ -456,6 +495,12 @@ static void *do_parking_thread(void *ignore)
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
while(pu) {
if (pu->notquiteyet) {
/* Pretend this one isn't here yet */
pl = pu;
pu = pu->next;
continue;
}
tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
if (tms > pu->parkingtime) {
/* They've been waiting too long, send them back to where they came. Theoretically they
@ -477,6 +522,13 @@ static void *do_parking_thread(void *ignore)
parkinglot = pu->next;
pt = pu;
pu = pu->next;
con = ast_context_find(parking_con);
if (con) {
snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
if (ast_context_remove_extension2(con, exten, 1, NULL))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
free(pt);
} else {
for (x=0;x<AST_MAX_FDS;x++) {
@ -498,6 +550,13 @@ static void *do_parking_thread(void *ignore)
parkinglot = pu->next;
pt = pu;
pu = pu->next;
con = ast_context_find(parking_con);
if (con) {
snprintf(exten, sizeof(exten), "%d", pt->parkingnum);
if (ast_context_remove_extension2(con, exten, 1, NULL))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
free(pt);
break;
} else {
@ -537,12 +596,37 @@ std: for (x=0;x<AST_MAX_FDS;x++) {
return NULL; /* Never reached */
}
static int park_call_exec(struct ast_channel *chan, void *data)
{
/* Data is unused at the moment but could contain a parking
lot context eventually */
int res=0;
struct localuser *u;
LOCAL_USER_ADD(u);
/* Setup the exten/priority to be s/1 since we don't know
where this call should return */
strcpy(chan->exten, "s");
chan->priority = 1;
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_safe_sleep(chan, 1000);
if (!res)
res = ast_park_call(chan, chan, 0, NULL);
LOCAL_USER_REMOVE(u);
if (!res)
res = AST_PBX_KEEPALIVE;
return res;
}
static int park_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
struct ast_channel *peer=NULL;
struct parkeduser *pu, *pl=NULL;
char exten[AST_MAX_EXTENSION];
struct ast_context *con;
int park;
int dres;
struct ast_bridge_config config;
@ -569,6 +653,13 @@ static int park_exec(struct ast_channel *chan, void *data)
ast_mutex_unlock(&parking_lock);
if (pu) {
peer = pu->chan;
con = ast_context_find(parking_con);
if (con) {
snprintf(exten, sizeof(exten), "%d", pu->parkingnum);
if (ast_context_remove_extension2(con, exten, 1, NULL))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
free(pu);
}
/* JK02: it helps to answer the channel if not already up */
@ -696,10 +787,8 @@ static int manager_parking_status( struct mansession *s, struct message *m )
int load_module(void)
{
int res;
int x;
int start, end;
struct ast_context *con;
char exten[AST_MAX_EXTENSION];
struct ast_config *cfg;
struct ast_variable *var;
@ -750,12 +839,11 @@ int load_module(void)
return -1;
}
}
for(x=parking_start; x<=parking_stop;x++) {
snprintf(exten, sizeof(exten), "%d", x);
ast_add_extension2(con, 1, exten, 1, NULL, parkedcall, strdup(exten), free, registrar);
}
ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, parkcall, strdup(""),free, registrar);
pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
if (!res)
res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
if (!res) {
ast_manager_register( "ParkedCalls", 0, manager_parking_status, "List parked calls" );
}
@ -802,7 +890,7 @@ int unload_module(void)
ast_manager_unregister( "ParkedCalls" );
ast_cli_unregister(&showparked);
ast_unregister_application(parkcall);
return ast_unregister_application(parkedcall);
}

Binary file not shown.
Loading…
Cancel
Save