These mods are to solve the problem in bug 7506. It's a lot of rework to solve a fairly small problem... such is life.

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@47303 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Steve Murphy
2006-11-07 23:46:41 +00:00
parent b3bf131dd8
commit 517978fd5f
23 changed files with 254 additions and 165 deletions

View File

@@ -29,6 +29,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
@@ -340,6 +341,21 @@ static int ast_check_hangup_locked(struct ast_channel *chan)
return res;
}
/*! \brief printf the string into a correctly sized mallocd buffer, and return the buffer */
char *ast_safe_string_alloc(const char *fmt, ...)
{
char *b2,buf[1];
int len;
va_list args;
va_start(args, fmt);
len = vsnprintf(buf, 1, fmt, args);
b2 = ast_malloc(len+1);
vsnprintf(b2, len+1, fmt, args);
va_end(args);
return b2;
}
/*! \brief Initiate system shutdown */
void ast_begin_shutdown(int hangup)
{
@@ -618,12 +634,13 @@ static const struct ast_channel_tech null_tech = {
};
/*! \brief Create a new channel structure */
struct ast_channel *ast_channel_alloc(int needqueue)
struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *name_fmt, ...)
{
struct ast_channel *tmp;
int x;
int flags;
struct varshead *headp;
va_list ap1, ap2;
/* If shutting down, don't allocate any new channels */
if (shutting_down) {
@@ -681,10 +698,10 @@ struct ast_channel *ast_channel_alloc(int needqueue)
/* And timing pipe */
tmp->fds[AST_TIMING_FD] = tmp->timingfd;
ast_string_field_set(tmp, name, "**Unknown**");
/* Initial state */
tmp->_state = AST_STATE_DOWN;
tmp->_state = state;
tmp->streamid = -1;
tmp->fin = global_fin;
@@ -698,6 +715,37 @@ struct ast_channel *ast_channel_alloc(int needqueue)
(long) time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
}
if (!ast_strlen_zero(name_fmt)) {
/* Almost every channel is calling this function, and setting the name via the ast_string_field_build() call.
* And they all use slightly different formats for their name string.
* This means, to set the name here, we have to accept variable args, and call the string_field_build from here.
* This means, that the stringfields must have a routine that takes the va_lists directly, and
* uses them to build the string, instead of forming the va_lists internally from the vararg ... list.
* This new function was written so this can be accomplished.
*/
va_start(ap1, name_fmt);
va_start(ap2, name_fmt);
ast_string_field_build_va(tmp, name, name_fmt, ap1, ap2);
va_end(ap1);
va_end(ap2);
/* and now, since the channel structure is built, and has its name, let's call the
* manager event generator with this Newchannel event. This is the proper and correct
* place to make this call, but you sure do have to pass a lot of data into this func
* to do it here!
*/
manager_event(EVENT_FLAG_CALL, "Newchannel",
"Channel: %s\r\n"
"State: %s\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
"Uniqueid: %s\r\n",
tmp->name, ast_state2str(state),
S_OR(cid_num, "<unknown>"),
S_OR(cid_name, "<unknown>"),
tmp->uniqueid);
}
headp = &tmp->varshead;
AST_LIST_HEAD_INIT_NOLOCK(headp);
@@ -2855,18 +2903,7 @@ struct ast_channel *ast_request(const char *type, int format, void *data, int *c
if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause)))
return NULL;
if (c->_state == AST_STATE_DOWN) {
manager_event(EVENT_FLAG_CALL, "Newchannel",
"Channel: %s\r\n"
"State: %s\r\n"
"CallerID: %s\r\n"
"CallerIDName: %s\r\n"
"Uniqueid: %s\r\n",
c->name, ast_state2str(c->_state),
S_OR(c->cid.cid_num, "<unknown>"),
S_OR(c->cid.cid_name, "<unknown>"),
c->uniqueid);
}
/* no need to generate a Newchannel event here; it is done in the channel_alloc call */
return c;
}
@@ -3508,8 +3545,9 @@ int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
chan->_state = state;
ast_device_state_changed_literal(chan->name);
/* setstate used to conditionally report Newchannel; this is no more */
manager_event(EVENT_FLAG_CALL,
(oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
"Newstate",
"Channel: %s\r\n"
"State: %s\r\n"
"CallerID: %s\r\n"

View File

@@ -4524,12 +4524,10 @@ int ast_async_goto(struct ast_channel *chan, const char *context, const char *ex
/* In order to do it when the channel doesn't really exist within
the PBX, we have to make a new channel, masquerade, and start the PBX
at the new location */
struct ast_channel *tmpchan = ast_channel_alloc(0);
struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, "AsyncGoto/%s", chan->name);
if (!tmpchan)
res = -1;
else {
ast_string_field_build(tmpchan, name, "AsyncGoto/%s", chan->name);
ast_setstate(tmpchan, chan->_state);
/* Make formats okay */
tmpchan->readformat = chan->readformat;
tmpchan->writeformat = chan->writeformat;
@@ -4886,7 +4884,7 @@ static void *async_wait(void *data)
static int ast_pbx_outgoing_cdr_failed(void)
{
/* allocate a channel */
struct ast_channel *chan = ast_channel_alloc(0);
struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0);
if (!chan)
return -1; /* failure */
@@ -4999,9 +4997,8 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
/* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
/* check if "failed" exists */
if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
chan = ast_channel_alloc(0);
chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "OutgoingSpoolFailed");
if (chan) {
ast_string_field_set(chan, name, "OutgoingSpoolFailed");
if (!ast_strlen_zero(context))
ast_copy_string(chan->context, context, sizeof(chan->context));
set_ext_pri(chan, "failed", 1);

View File

@@ -877,15 +877,11 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr
return result;
}
void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
ast_string_field *fields, int num_fields,
int index, const char *format, ...)
int index, const char *format, va_list ap1, va_list ap2)
{
size_t needed;
va_list ap1, ap2;
va_start(ap1, format);
va_start(ap2, format); /* va_copy does not exist on FreeBSD */
needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1;
@@ -906,7 +902,20 @@ void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
fields[index] = mgr->pool->base + mgr->used;
mgr->used += needed;
mgr->space -= needed;
}
void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
ast_string_field *fields, int num_fields,
int index, const char *format, ...)
{
va_list ap1, ap2;
va_start(ap1, format);
va_start(ap2, format); /* va_copy does not exist on FreeBSD */
__ast_string_field_index_build_va(mgr, fields, num_fields, index, format, ap1, ap2);
va_end(ap1);
va_end(ap2);
}