diff options
author | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-09 15:31:32 +0000 |
---|---|---|
committer | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-09 15:31:32 +0000 |
commit | 0eb1e5407a6eacd46d98e134dc81e8b857c103b7 (patch) | |
tree | 0b1d16ff83df2f35441f03a082b848262b8a2557 /main/channel.c | |
parent | 6c57cdc6ac82a6a6700ebdb788d690471d8fc49d (diff) |
Merge Call completion support into trunk.
From Reviewboard:
CCSS stands for Call Completion Supplementary Services. An admittedly out-of-date
overview of the architecture can be found in the file doc/CCSS_architecture.pdf
in the CCSS branch. Off the top of my head, the big differences between what is
implemented and what is in the document are as follows:
1. We did not end up modifying the Hangup application at all.
2. The document states that a single call completion monitor may be used across
multiple calls to the same device. This proved to not be such a good idea
when implementing protocol-specific monitors, and so we ended up using one
monitor per-device per-call.
3. There are some configuration options which were conceived after the document
was written. These are documented in the ccss.conf.sample that is on this
review request.
For some basic understanding of terminology used throughout this code, see the
ccss.tex document that is on this review.
This implements CCBS and CCNR in several flavors.
First up is a "generic" implementation, which can work over any channel technology
provided that the channel technology can accurately report device state. Call
completion is requested using the dialplan application CallCompletionRequest and can
be canceled using CallCompletionCancel. Device state subscriptions are used in order
to monitor the state of called parties.
Next, there is a SIP-specific implementation of call completion. This method uses the
methods outlined in draft-ietf-bliss-call-completion-06 to implement call completion
using SIP signaling. There are a few things to note here:
* The agent/monitor terminology used throughout Asterisk sometimes is the reverse of
what is defined in the referenced draft.
* Implementation of the draft required support for SIP PUBLISH. I attempted to write
this in a generic-enough fashion such that if someone were to want to write PUBLISH
support for other event packages, such as dialog-state or presence, most of the effort
would be in writing callbacks specific to the event package.
* A subportion of supporting PUBLISH reception was that we had to implement a PIDF
parser. The PIDF support added is a bit minimal. I first wrote a validation
routine to ensure that the PIDF document is formatted properly. The rest of the
PIDF reading is done in-line in the call-completion-specific PUBLISH-handling
code. In other words, while there is PIDF support here, it is not in any state
where it could easily be applied to other event packages as is.
Finally, there are a variety of ISDN-related call completion protocols supported. These
were written by Richard Mudgett, and as such I can't really say much about their
implementation. There are notes in the CHANGES file that indicate the ISDN protocols
over which call completion is supported.
Review: https://reviewboard.asterisk.org/r/523
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@256528 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/channel.c')
-rw-r--r-- | main/channel.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/main/channel.c b/main/channel.c index 5be973a49..03c657cff 100644 --- a/main/channel.c +++ b/main/channel.c @@ -2239,6 +2239,7 @@ int ast_hangup(struct ast_channel *chan) } ast_channel_unlock(chan); + ast_cc_offer(chan); ast_manager_event(chan, EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n" "Uniqueid: %s\r\n" @@ -3611,6 +3612,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con case AST_CONTROL_TRANSFER: case AST_CONTROL_T38_PARAMETERS: case _XXX_AST_CONTROL_T38: + case AST_CONTROL_CC: break; case AST_CONTROL_CONGESTION: @@ -3754,6 +3756,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, case AST_CONTROL_TRANSFER: case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_REDIRECTING: + case AST_CONTROL_CC: /* Nothing left to do for these. */ res = 0; break; @@ -4477,6 +4480,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co case AST_CONTROL_SRCCHANGE: case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_REDIRECTING: + case AST_CONTROL_CC: case -1: /* Ignore -- just stopping indications */ break; @@ -7444,6 +7448,107 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc return retval; } +static void *channel_cc_params_copy(void *data) +{ + const struct ast_cc_config_params *src = data; + struct ast_cc_config_params *dest = ast_cc_config_params_init(); + if (!dest) { + return NULL; + } + ast_cc_copy_config_params(dest, src); + return dest; +} + +static void channel_cc_params_destroy(void *data) +{ + struct ast_cc_config_params *cc_params = data; + ast_cc_config_params_destroy(cc_params); +} + +static const struct ast_datastore_info cc_channel_datastore_info = { + .type = "Call Completion", + .duplicate = channel_cc_params_copy, + .destroy = channel_cc_params_destroy, +}; + +int ast_channel_cc_params_init(struct ast_channel *chan, + const struct ast_cc_config_params *base_params) +{ + struct ast_cc_config_params *cc_params; + struct ast_datastore *cc_datastore; + + if (!(cc_params = ast_cc_config_params_init())) { + return -1; + } + + if (!(cc_datastore = ast_datastore_alloc(&cc_channel_datastore_info, NULL))) { + ast_cc_config_params_destroy(cc_params); + return -1; + } + + if (base_params) { + ast_cc_copy_config_params(cc_params, base_params); + } + cc_datastore->data = cc_params; + ast_channel_datastore_add(chan, cc_datastore); + return 0; +} + +struct ast_cc_config_params *ast_channel_get_cc_config_params(struct ast_channel *chan) +{ + struct ast_datastore *cc_datastore; + + if (!(cc_datastore = ast_channel_datastore_find(chan, &cc_channel_datastore_info, NULL))) { + /* If we can't find the datastore, it almost definitely means that the channel type being + * used has not had its driver modified to parse CC config parameters. The best action + * to take here is to create the parameters on the spot with the defaults set. + */ + if (ast_channel_cc_params_init(chan, NULL)) { + return NULL; + } + if (!(cc_datastore = ast_channel_datastore_find(chan, &cc_channel_datastore_info, NULL))) { + /* Should be impossible */ + return NULL; + } + } + + ast_assert(cc_datastore->data != NULL); + return cc_datastore->data; +} + +int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length) +{ + int len = name_buffer_length; + char *dash; + if (!ast_channel_queryoption(chan, AST_OPTION_DEVICE_NAME, device_name, &len, 0)) { + return 0; + } + + /* Dang. Do it the old-fashioned way */ + ast_copy_string(device_name, chan->name, name_buffer_length); + if ((dash = strrchr(device_name, '-'))) { + *dash = '\0'; + } + + return 0; +} + +int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, size_t size) +{ + int len = size; + char *slash; + + if (!ast_channel_queryoption(chan, AST_OPTION_CC_AGENT_TYPE, agent_type, &len, 0)) { + return 0; + } + + ast_copy_string(agent_type, chan->name, size); + if ((slash = strchr(agent_type, '/'))) { + *slash = '\0'; + } + return 0; +} + /* DO NOT PUT ADDITIONAL FUNCTIONS BELOW THIS BOUNDARY * * ONLY FUNCTIONS FOR PROVIDING BACKWARDS ABI COMPATIBILITY BELONG HERE |