[asterisk-commits] rmudgett: branch group/CCSS r240714 - in /team/group/CCSS: channels/ include/...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Jan 15 23:10:50 CST 2010
Author: rmudgett
Date: Fri Jan 15 23:10:46 2010
New Revision: 240714
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=240714
Log:
Stop monitor CC available routines from trying to figure out the monitor type.
cc_build_payload() was trying to figure out what monitor type to use based
upon the monitor policy and the channel name. Not a good thing. So I
made it take a monitor type parameter. Most of the other changes are
ripple effects of this change. In the process, I fixed a bunch of
failure conditions and added more doxygen comments.
Modified:
team/group/CCSS/channels/chan_dahdi.c
team/group/CCSS/include/asterisk/ccss.h
team/group/CCSS/main/ccss.c
Modified: team/group/CCSS/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/channels/chan_dahdi.c?view=diff&rev=240714&r1=240713&r2=240714
==============================================================================
--- team/group/CCSS/channels/chan_dahdi.c (original)
+++ team/group/CCSS/channels/chan_dahdi.c Fri Jan 15 23:10:46 2010
@@ -7962,7 +7962,7 @@
return f;
}
-static int dahdi_cc_is_possible(struct ast_channel *chan, const char * const device_name)
+static const char *dahdi_cc_is_possible(struct ast_channel *chan, const char * const device_name)
{
struct ast_cc_config_params *cc_params = ast_channel_get_cc_config_params(chan);
enum ast_cc_monitor_policies monitor_policy = ast_get_cc_monitor_policy(cc_params);
@@ -7973,14 +7973,14 @@
} else if (monitor_policy == AST_CC_MONITOR_NATIVE) {
monitor_type = "DAHDI";
} else {
- return 0;
+ return NULL;
}
if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
- return 0;
- }
-
- return 1;
+ return NULL;
+ }
+
+ return monitor_type;
}
static struct ast_frame *dahdi_read(struct ast_channel *ast)
@@ -8059,24 +8059,24 @@
if (p->subs[idx].needringing) {
if (!p->subs[idx].ccframesent) {
char device_name[256];
+ const char *monitor_type;
+
ast_channel_get_device_name(p->owner, device_name, sizeof(device_name));
- if (dahdi_cc_is_possible(p->owner, device_name)) {
- /* XXX I'm going to need an indication that I've sent a CC frame so I don't
- * just keep sending them forever
- */
- if (!ast_cc_build_frame(p->owner, p->cc_params, device_name, p->dialstring, AST_CC_CCNR, &p->subs[idx].f)) {
- p->subs[idx].needringing = 0;
- return &p->subs[idx].f;
- }
- }
- /* Even if we didn't really send a CC frame, we need to set this
+ monitor_type = dahdi_cc_is_possible(p->owner, device_name);
+ if (monitor_type
+ && !ast_cc_build_frame(p->owner, p->cc_params, monitor_type, device_name, p->dialstring, AST_CC_CCNR, &p->subs[idx].f)) {
+ p->subs[idx].ccframesent = 1;
+ return &p->subs[idx].f;
+ }
+ /*
+ * If CC isn't possible or if we can't build the CC frame properly,
+ * then we drop into the typical behavior instead.
+ *
+ * Even if we didn't really send a CC frame, we need to set this
* true so that we don't repeatedly attempt to send them and never
* send a ringing frame.
*/
p->subs[idx].ccframesent = 1;
- /* If CC isn't possible or if we can't build the CC frame properly,
- * then we drop into the typical behavior instead
- */
}
/* Send ringing frame if requested */
p->subs[idx].needringing = 0;
@@ -12321,6 +12321,21 @@
return tmp;
}
+/*!
+ * \brief Callback made when dial failed to get a channel out of dahdi_request().
+ * \since 1.8
+ *
+ * \param inbound Incoming asterisk channel.
+ * \param dest Same dial string passed to dahdi_request().
+ * \param callback Callback into CC core to announce a busy channel available for CC.
+ *
+ * \details
+ * This callback acts like a forked dial with all prongs of the fork busy.
+ * Essentially, for each channel that could have taken the call, indicate that
+ * it is busy.
+ *
+ * \return Nothing
+ */
static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
{
struct dahdi_pvt *p, *exitpvt;
@@ -12337,25 +12352,53 @@
for (;;) {
if (is_group_or_channel_match(p, groupmatch, &groupmatched, channelmatch, &channelmatched)) {
/* We found a potential match. call the callback */
- struct ast_str *interface_name;
+ struct ast_str *device_name;
+ char *dash;
+ const char *monitor_type;
char dialstring[AST_CHANNEL_NAME];
- char full_interface_name[AST_CHANNEL_NAME];
+ char full_device_name[AST_CHANNEL_NAME];
+
+ switch (ast_get_cc_monitor_policy(p->cc_params)) {
+ case AST_CC_MONITOR_NEVER:
+ break;
+ case AST_CC_MONITOR_NATIVE:
+ case AST_CC_MONITOR_ALWAYS:
+ case AST_CC_MONITOR_GENERIC:
#if defined(HAVE_PRI)
- char address[AST_CHANNEL_NAME];
-
- if (dahdi_sig_pri_lib_handles(p->sig)) {
- sig_pri_extract_called_num_subaddr(p->sig_pvt, dest, address, sizeof(address));
- } else {
- address[0] = '\0';
- }
- interface_name = create_channel_name(p, 1, address);
+ if (dahdi_sig_pri_lib_handles(p->sig)) {
+ char address[AST_CHANNEL_NAME];
+
+ sig_pri_extract_called_num_subaddr(p->sig_pvt, dest, address, sizeof(address));
+ device_name = create_channel_name(p, 1, address);
+ } else {
+ device_name = create_channel_name(p, 1, "");
+ }
#else
- interface_name = create_channel_name(p);
+ device_name = create_channel_name(p);
#endif /* defined(HAVE_PRI) */
- snprintf(full_interface_name, sizeof(full_interface_name), "DAHDI/%s", ast_str_buffer(interface_name));
- snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
- callback(inbound, p->cc_params, full_interface_name, dialstring);
- ast_free(interface_name);
+ snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s", ast_str_buffer(device_name));
+ ast_free(device_name);
+ /*
+ * The portion after the '-' in the channel name is either a random
+ * number, a sequence number, or a subchannel number. None are
+ * necessary so strip them off.
+ */
+ dash = strrchr(full_device_name, '-');
+ if (dash) {
+ *dash = '\0';
+ }
+ snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
+
+ /*
+ * Analog can only do generic monitoring.
+ * ISDN is in a trunk busy condition and any "device" is going
+ * to be busy until a B channel becomes available. The generic
+ * monitor can be made to do this task.
+ */
+ monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
+ callback(inbound, p->cc_params, monitor_type, full_device_name, dialstring);
+ break;
+ }
}
p = backwards ? p->prev : p->next;
if (!p) {
Modified: team/group/CCSS/include/asterisk/ccss.h
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/include/asterisk/ccss.h?view=diff&rev=240714&r1=240713&r2=240714
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Fri Jan 15 23:10:46 2010
@@ -1435,6 +1435,12 @@
* \since 1.8
* \brief Callback made from ast_cc_callback for certain channel types
*
+ * \param inbound Incoming asterisk channel.
+ * \param cc_params The CC configuration parameters for the outbound target
+ * \param monitor_type The type of monitor to use when CC is requested
+ * \param device_name The name of the outbound target device.
+ * \param dialable_name The dial string used when calling this specific interface
+ *
* \details
* For channel types that fail ast_request when the device is busy, we call into the
* channel driver with ast_cc_callback. This is the callback that is called in that
@@ -1446,7 +1452,7 @@
* by the channel driver.
*/
void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
- const char * const interface_name, const char * const dialable_name);
+ const char *monitor_type, const char * const device_name, const char * const dialable_name);
/*!
* \since 1.8
@@ -1460,7 +1466,8 @@
*
* \param chan A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided
* \param cc_params The CC configuration parameters for the outbound target
- * \param interface_name The name of the outbound target
+ * \param monitor_type The type of monitor to use when CC is requested
+ * \param device_name The name of the outbound target device.
* \param dialable_name The dial string used when calling this specific interface
* \param service What kind of CC service is being offered. (CCBS/CCNR/etc...)
* \param[out] frame. The frame we will be returning to the caller. It is vital that ast_frame_free be called on this frame since the
@@ -1469,11 +1476,29 @@
* \retval 0 Success
*/
int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
- const char * const interface_name, const char * const dialable_name, enum ast_cc_service_type service,
- struct ast_frame *frame);
-
+ const char *monitor_type, const char * const device_name,
+ const char * const dialable_name, enum ast_cc_service_type service, struct ast_frame *frame);
+
+
+/*!
+ * \brief Callback made from ast_cc_callback for certain channel types
+ * \since 1.8
+ *
+ * \param chan A channel involved in the call. What we want is on a datastore on both incoming and outgoing so either may be provided
+ * \param cc_params The CC configuration parameters for the outbound target
+ * \param monitor_type The type of monitor to use when CC is requested
+ * \param device_name The name of the outbound target device.
+ * \param dialable_name The dial string used when calling this specific interface
+ *
+ * \details
+ * For channel types that fail ast_request when the device is busy, we call into the
+ * channel driver with ast_cc_callback. This is the callback that is called in that
+ * case for each device found which could have been returned by ast_request.
+ *
+ * \return Nothing
+ */
typedef void (*ast_cc_callback_fn)(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
- const char * const interface_name, const char * const dialable_name);
+ const char *monitor_type, const char * const device_name, const char * const dialable_name);
/*!
* \since 1.8
Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=240714&r1=240713&r2=240714
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Fri Jan 15 23:10:46 2010
@@ -1555,8 +1555,18 @@
}
struct ast_control_cc_payload {
+ /*!
+ * \note This really should be an array of characters in case this payload
+ * is sent accross an IAX2 link. However, this would not make too much sense
+ * given this type may not be recognized by the other end.
+ * Protection may be necessary to prevent it from being transmitted.
+ *
+ * In addition the following other problems are also possible:
+ * 1) Endian issues with the integers/enums stored in the config_params.
+ * 2) Alignment padding issues for the element types.
+ */
+ const char *monitor_type;
enum ast_cc_service_type service;
- const char *monitor_type;
struct ast_cc_config_params config_params;
int parent_interface_id;
char device_name[AST_CHANNEL_NAME];
@@ -3318,48 +3328,28 @@
}
static int cc_build_payload(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
- const char * const interface_name, const char * dialable_name,
- enum ast_cc_service_type service, struct ast_control_cc_payload *payload)
+ const char *monitor_type, const char * const device_name, const char * dialable_name,
+ enum ast_cc_service_type service, struct ast_control_cc_payload *payload)
{
struct ast_datastore *datastore;
struct dialed_cc_interfaces *cc_interfaces;
- enum ast_cc_monitor_policies monitor_policy = ast_get_cc_monitor_policy(cc_params);
- const char *interface_name_copy = ast_strdupa(interface_name);
int dial_parent_id;
ast_channel_lock(chan);
- if (!(datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL))) {
+ datastore = ast_channel_datastore_find(chan, &dialed_cc_interfaces_info, NULL);
+ if (!datastore) {
ast_channel_unlock(chan);
return -1;
}
-
cc_interfaces = datastore->data;
dial_parent_id = cc_interfaces->dial_parent_id;
ast_channel_unlock(chan);
+ payload->monitor_type = monitor_type;
payload->service = service;
- if (monitor_policy == AST_CC_MONITOR_GENERIC || monitor_policy == AST_CC_MONITOR_ALWAYS) {
- payload->monitor_type = "generic";
- } else if (monitor_policy == AST_CC_MONITOR_NATIVE) {
- char *slash = strchr(interface_name_copy, '/');
- const struct ast_cc_monitor_callbacks *callbacks;
- if (!slash) {
- ast_log_dynamic_level(cc_logger_level, "Unable to determine proper CC monitor type.\n");
- return -1;
- }
- *slash = '\0';
- if (!(callbacks = find_monitor_callbacks(interface_name_copy))) {
- ast_log_dynamic_level(cc_logger_level, "No monitor type corresponds to %s\n", interface_name_copy);
- return -1;
- }
- payload->monitor_type = callbacks->type;
- } else { /* AST_CC_MONITOR_NEVER */
- ast_log_dynamic_level(cc_logger_level, "Interface %s does not allow CC\n", interface_name);
- return -1;
- }
ast_cc_copy_config_params(&payload->config_params, cc_params);
payload->parent_interface_id = dial_parent_id;
- ast_copy_string(payload->device_name, interface_name, sizeof(payload->device_name));
+ ast_copy_string(payload->device_name, device_name, sizeof(payload->device_name));
ast_copy_string(payload->dialable_name, dialable_name, sizeof(payload->dialable_name));
return 0;
}
@@ -3368,17 +3358,21 @@
const char * const dialable_name, enum ast_cc_service_type service)
{
struct ast_frame frame = {0,};
- char chan_name[AST_CHANNEL_NAME];
+ char device_name[AST_CHANNEL_NAME];
int retval;
-
- ast_channel_get_device_name(chan, chan_name, sizeof(chan_name));
-
- if (ast_cc_monitor_count(chan_name, monitor_type) >= ast_get_cc_max_monitors(ast_channel_get_cc_config_params(chan))) {
- ast_log(LOG_NOTICE, "Not queuing a CC frame for channel %s since it already has its maximum monitors allocated\n", chan_name);
- return -1;
- }
-
- if (ast_cc_build_frame(chan, ast_channel_get_cc_config_params(chan), chan_name, dialable_name, service, &frame)) {
+ struct ast_cc_config_params *cc_params;
+
+ cc_params = ast_channel_get_cc_config_params(chan);
+ if (!cc_params) {
+ return -1;
+ }
+ ast_channel_get_device_name(chan, device_name, sizeof(device_name));
+ if (ast_cc_monitor_count(device_name, monitor_type) >= ast_get_cc_max_monitors(cc_params)) {
+ ast_log(LOG_NOTICE, "Not queuing a CC frame for device %s since it already has its maximum monitors allocated\n", device_name);
+ return -1;
+ }
+
+ if (ast_cc_build_frame(chan, cc_params, monitor_type, device_name, dialable_name, service, &frame)) {
/* Frame building failed. We can't use this. */
return -1;
}
@@ -3387,11 +3381,16 @@
return retval;
}
-int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params, const char * const interface_name,
- const char * const dialable_name, enum ast_cc_service_type service, struct ast_frame *frame)
+int ast_cc_build_frame(struct ast_channel *chan, struct ast_cc_config_params *cc_params,
+ const char *monitor_type, const char * const device_name,
+ const char * const dialable_name, enum ast_cc_service_type service, struct ast_frame *frame)
{
struct ast_control_cc_payload *payload = ast_calloc(1, sizeof(*payload));
- if (cc_build_payload(chan, cc_params, interface_name, dialable_name, service, payload)) {
+
+ if (!payload) {
+ return -1;
+ }
+ if (cc_build_payload(chan, cc_params, monitor_type, device_name, dialable_name, service, payload)) {
/* Something screwed up, we can't make a frame with this */
ast_free(payload);
return -1;
@@ -3408,6 +3407,8 @@
{
char device_name[AST_CHANNEL_NAME];
struct ast_control_cc_payload payload;
+ struct ast_cc_config_params *cc_params;
+
if (outgoing->hangupcause != AST_CAUSE_BUSY && outgoing->hangupcause != AST_CAUSE_CONGESTION) {
/* It doesn't make sense to try to offer CCBS to the caller if the reason for ast_call
* failing is something other than busy or congestion
@@ -3415,7 +3416,11 @@
return;
}
- if (ast_get_cc_monitor_policy(ast_channel_get_cc_config_params(outgoing)) != AST_CC_MONITOR_GENERIC) {
+ cc_params = ast_channel_get_cc_config_params(outgoing);
+ if (!cc_params) {
+ return;
+ }
+ if (ast_get_cc_monitor_policy(cc_params) != AST_CC_MONITOR_GENERIC) {
/* This sort of CCBS only works if using generic CC. For native, we would end up sending
* a CC request for a non-existent call. The far end will reject this every time
*/
@@ -3423,16 +3428,19 @@
}
ast_channel_get_device_name(outgoing, device_name, sizeof(device_name));
- cc_build_payload(outgoing, ast_channel_get_cc_config_params(outgoing), device_name,
- dialstring, AST_CC_CCBS, &payload);
+ if (cc_build_payload(outgoing, cc_params, AST_CC_GENERIC_MONITOR_TYPE, device_name,
+ dialstring, AST_CC_CCBS, &payload)) {
+ /* Something screwed up, we can't make a frame with this */
+ return;
+ }
ast_handle_cc_control_frame(incoming, outgoing, &payload);
}
void ast_cc_busy_interface(struct ast_channel *inbound, struct ast_cc_config_params *cc_params,
- const char * const interface_name, const char * const dialable_name)
+ const char *monitor_type, const char * const device_name, const char * const dialable_name)
{
struct ast_control_cc_payload payload;
- if (cc_build_payload(inbound, cc_params, interface_name, dialable_name, AST_CC_CCBS, &payload)) {
+ if (cc_build_payload(inbound, cc_params, monitor_type, device_name, dialable_name, AST_CC_CCBS, &payload)) {
/* Something screwed up. Don't try to handle this payload */
return;
}
More information about the asterisk-commits
mailing list