diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 72 | ||||
-rw-r--r-- | main/pbx.c | 9 | ||||
-rw-r--r-- | main/utils.c | 21 |
3 files changed, 73 insertions, 29 deletions
diff --git a/main/channel.c b/main/channel.c index 992a6a539..865c9ca75 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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" diff --git a/main/pbx.c b/main/pbx.c index 2acf75888..7002819be 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -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); diff --git a/main/utils.c b/main/utils.c index b1c154131..ff226fc11 100644 --- a/main/utils.c +++ b/main/utils.c @@ -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); } |