Directed Call Pickup Support. More...
#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/features.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cel.h"
Go to the source code of this file.
Data Structures | |
struct | pickup_by_name_args |
Defines | |
#define | PICKUPMARK "PICKUPMARK" |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Directed Call Pickup Application") | |
static int | find_by_mark (void *obj, void *arg, void *data, int flags) |
static int | find_by_part (void *obj, void *arg, void *data, int flags) |
static int | find_channel_by_group (void *obj, void *arg, void *data, int flags) |
static int | load_module (void) |
static struct ast_channel * | my_ast_get_channel_by_name_locked (const char *channame) |
Helper Function to walk through ALL channels checking NAME and STATE. | |
static int | pickup_by_channel (struct ast_channel *chan, char *pickup) |
Attempt to pick up named channel, does not use context. | |
static int | pickup_by_exten (struct ast_channel *chan, const char *exten, const char *context) |
static int | pickup_by_group (struct ast_channel *chan) |
static int | pickup_by_mark (struct ast_channel *chan, const char *mark) |
static int | pickup_by_name_cb (void *obj, void *arg, void *data, int flags) |
static int | pickup_by_part (struct ast_channel *chan, const char *part) |
static int | pickup_exec (struct ast_channel *chan, const char *data) |
static int | pickupchan_exec (struct ast_channel *chan, const char *data) |
static int | unload_module (void) |
Variables | |
static const char | app [] = "Pickup" |
static const char | app2 [] = "PickupChan" |
Directed Call Pickup Support.
Definition in file app_directed_pickup.c.
#define PICKUPMARK "PICKUPMARK" |
Definition at line 51 of file app_directed_pickup.c.
Referenced by find_by_mark(), and pickup_exec().
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Directed Call Pickup Application" | ||||
) |
static int find_by_mark | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
< Potential pickup target
Definition at line 221 of file app_directed_pickup.c.
References ast_can_pickup(), ast_channel_lock, ast_channel_unlock, CMP_MATCH, CMP_STOP, pbx_builtin_getvar_helper(), and PICKUPMARK.
Referenced by pickup_by_mark().
00222 { 00223 struct ast_channel *target = obj;/*!< Potential pickup target */ 00224 const char *mark = data; 00225 const char *tmp; 00226 00227 ast_channel_lock(target); 00228 tmp = pbx_builtin_getvar_helper(target, PICKUPMARK); 00229 if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) { 00230 /* Return with the channel still locked on purpose */ 00231 return CMP_MATCH | CMP_STOP; 00232 } 00233 ast_channel_unlock(target); 00234 00235 return 0; 00236 }
static int find_by_part | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
< Potential pickup target
Definition at line 321 of file app_directed_pickup.c.
References ast_can_pickup(), ast_channel_lock, ast_channel_unlock, CMP_MATCH, CMP_STOP, and len().
Referenced by pickup_by_part().
00322 { 00323 struct ast_channel *target = obj;/*!< Potential pickup target */ 00324 const char *part = data; 00325 int len = strlen(part); 00326 00327 ast_channel_lock(target); 00328 if (len <= strlen(target->name) && !strncmp(target->name, part, len) 00329 && ast_can_pickup(target)) { 00330 /* Return with the channel still locked on purpose */ 00331 return CMP_MATCH | CMP_STOP; 00332 } 00333 ast_channel_unlock(target); 00334 00335 return 0; 00336 }
static int find_channel_by_group | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
< Potential pickup target
< Channel wanting to pickup call
Definition at line 255 of file app_directed_pickup.c.
References ast_can_pickup(), ast_channel_lock, ast_channel_unlock, ast_channel::callgroup, CMP_MATCH, CMP_STOP, and ast_channel::pickupgroup.
Referenced by pickup_by_group().
00256 { 00257 struct ast_channel *target = obj;/*!< Potential pickup target */ 00258 struct ast_channel *chan = data;/*!< Channel wanting to pickup call */ 00259 00260 ast_channel_lock(target); 00261 if (chan != target && (chan->pickupgroup & target->callgroup) 00262 && ast_can_pickup(target)) { 00263 /* Return with the channel still locked on purpose */ 00264 return CMP_MATCH | CMP_STOP; 00265 } 00266 ast_channel_unlock(target); 00267 00268 return 0; 00269 }
static int load_module | ( | void | ) | [static] |
Definition at line 409 of file app_directed_pickup.c.
References ast_register_application_xml, pickup_exec(), and pickupchan_exec().
00410 { 00411 int res; 00412 00413 res = ast_register_application_xml(app, pickup_exec); 00414 res |= ast_register_application_xml(app2, pickupchan_exec); 00415 00416 return res; 00417 }
static struct ast_channel* my_ast_get_channel_by_name_locked | ( | const char * | channame | ) | [static, read] |
Helper Function to walk through ALL channels checking NAME and STATE.
Definition at line 143 of file app_directed_pickup.c.
References ast_alloca, ast_channel_callback(), pickup_by_name_args::len, pickup_by_name_args::name, and pickup_by_name_cb().
Referenced by pickup_by_channel().
00144 { 00145 char *chkchan; 00146 struct pickup_by_name_args pickup_args; 00147 00148 /* Check if channel name contains a '-'. 00149 * In this case the channel name will be interpreted as full channel name. 00150 */ 00151 if (strchr(channame, '-')) { 00152 /* check full channel name */ 00153 pickup_args.len = strlen(channame); 00154 pickup_args.name = channame; 00155 } else { 00156 /* need to append a '-' for the comparison so we check full channel name, 00157 * i.e SIP/hgc- , use a temporary variable so original stays the same for 00158 * debugging. 00159 */ 00160 pickup_args.len = strlen(channame) + 1; 00161 chkchan = ast_alloca(pickup_args.len + 1); 00162 strcpy(chkchan, channame); 00163 strcat(chkchan, "-"); 00164 pickup_args.name = chkchan; 00165 } 00166 00167 return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0); 00168 }
static int pickup_by_channel | ( | struct ast_channel * | chan, | |
char * | pickup | |||
) | [static] |
Attempt to pick up named channel, does not use context.
< Potential pickup target
Definition at line 171 of file app_directed_pickup.c.
References ast_channel_unlock, ast_channel_unref, ast_do_pickup(), and my_ast_get_channel_by_name_locked().
Referenced by pickupchan_exec().
00172 { 00173 int res = -1; 00174 struct ast_channel *target;/*!< Potential pickup target */ 00175 00176 target = my_ast_get_channel_by_name_locked(pickup); 00177 if (target) { 00178 /* Just check that we are not picking up the SAME as target. (i.e. ourself) */ 00179 if (chan != target) { 00180 res = ast_do_pickup(chan, target); 00181 } 00182 ast_channel_unlock(target); 00183 target = ast_channel_unref(target); 00184 } 00185 00186 return res; 00187 }
static int pickup_by_exten | ( | struct ast_channel * | chan, | |
const char * | exten, | |||
const char * | context | |||
) | [static] |
< Potential pickup target
Definition at line 190 of file app_directed_pickup.c.
References ast_can_pickup(), ast_channel_iterator_by_exten_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_do_pickup(), ast_log(), and LOG_NOTICE.
Referenced by pickup_exec().
00191 { 00192 struct ast_channel *target = NULL;/*!< Potential pickup target */ 00193 struct ast_channel_iterator *iter; 00194 int res = -1; 00195 00196 if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) { 00197 return -1; 00198 } 00199 00200 while ((target = ast_channel_iterator_next(iter))) { 00201 ast_channel_lock(target); 00202 if ((chan != target) && ast_can_pickup(target)) { 00203 ast_log(LOG_NOTICE, "%s pickup by %s\n", target->name, chan->name); 00204 break; 00205 } 00206 ast_channel_unlock(target); 00207 target = ast_channel_unref(target); 00208 } 00209 00210 ast_channel_iterator_destroy(iter); 00211 00212 if (target) { 00213 res = ast_do_pickup(chan, target); 00214 ast_channel_unlock(target); 00215 target = ast_channel_unref(target); 00216 } 00217 00218 return res; 00219 }
static int pickup_by_group | ( | struct ast_channel * | chan | ) | [static] |
< Potential pickup target
Definition at line 271 of file app_directed_pickup.c.
References ast_channel_callback(), ast_channel_unlock, ast_channel_unref, ast_do_pickup(), ast_log(), find_channel_by_group(), and LOG_NOTICE.
Referenced by pickup_exec().
00272 { 00273 struct ast_channel *target;/*!< Potential pickup target */ 00274 int res = -1; 00275 00276 /* The found channel is already locked. */ 00277 target = ast_channel_callback(find_channel_by_group, NULL, chan, 0); 00278 if (target) { 00279 ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", target->name, chan->name); 00280 res = ast_do_pickup(chan, target); 00281 ast_channel_unlock(target); 00282 target = ast_channel_unref(target); 00283 } 00284 00285 return res; 00286 }
static int pickup_by_mark | ( | struct ast_channel * | chan, | |
const char * | mark | |||
) | [static] |
< Potential pickup target
Definition at line 239 of file app_directed_pickup.c.
References ast_channel_callback(), ast_channel_unlock, ast_channel_unref, ast_do_pickup(), and find_by_mark().
Referenced by pickup_exec().
00240 { 00241 struct ast_channel *target;/*!< Potential pickup target */ 00242 int res = -1; 00243 00244 /* The found channel is already locked. */ 00245 target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0); 00246 if (target) { 00247 res = ast_do_pickup(chan, target); 00248 ast_channel_unlock(target); 00249 target = ast_channel_unref(target); 00250 } 00251 00252 return res; 00253 }
static int pickup_by_name_cb | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
< Potential pickup target
Definition at line 127 of file app_directed_pickup.c.
References args, ast_can_pickup(), ast_channel_lock, ast_channel_unlock, CMP_MATCH, CMP_STOP, pickup_by_name_args::len, and pickup_by_name_args::name.
Referenced by my_ast_get_channel_by_name_locked().
00128 { 00129 struct ast_channel *target = obj;/*!< Potential pickup target */ 00130 struct pickup_by_name_args *args = data; 00131 00132 ast_channel_lock(target); 00133 if (!strncasecmp(target->name, args->name, args->len) && ast_can_pickup(target)) { 00134 /* Return with the channel still locked on purpose */ 00135 return CMP_MATCH | CMP_STOP; 00136 } 00137 ast_channel_unlock(target); 00138 00139 return 0; 00140 }
static int pickup_by_part | ( | struct ast_channel * | chan, | |
const char * | part | |||
) | [static] |
< Potential pickup target
Definition at line 339 of file app_directed_pickup.c.
References ast_channel_callback(), ast_channel_unlock, ast_channel_unref, ast_do_pickup(), and find_by_part().
Referenced by pickupchan_exec().
00340 { 00341 struct ast_channel *target;/*!< Potential pickup target */ 00342 int res = -1; 00343 00344 /* The found channel is already locked. */ 00345 target = ast_channel_callback(find_by_part, NULL, (char *) part, 0); 00346 if (target) { 00347 res = ast_do_pickup(chan, target); 00348 ast_channel_unlock(target); 00349 target = ast_channel_unref(target); 00350 } 00351 00352 return res; 00353 }
static int pickup_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 289 of file app_directed_pickup.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), ast_channel::context, context, exten, LOG_NOTICE, pickup_by_exten(), pickup_by_group(), pickup_by_mark(), and PICKUPMARK.
Referenced by load_module().
00290 { 00291 char *tmp = ast_strdupa(data); 00292 char *exten = NULL, *context = NULL; 00293 00294 if (ast_strlen_zero(data)) { 00295 return pickup_by_group(chan) ? 0 : -1; 00296 } 00297 00298 /* Parse extension (and context if there) */ 00299 while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) { 00300 if ((context = strchr(exten, '@'))) 00301 *context++ = '\0'; 00302 if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) { 00303 if (!pickup_by_mark(chan, exten)) { 00304 /* Pickup successful. Stop the dialplan this channel is a zombie. */ 00305 return -1; 00306 } 00307 } else { 00308 if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context)) { 00309 /* Pickup successful. Stop the dialplan this channel is a zombie. */ 00310 return -1; 00311 } 00312 } 00313 ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten); 00314 } 00315 00316 /* Pickup failed. Keep going in the dialplan. */ 00317 return 0; 00318 }
static int pickupchan_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 356 of file app_directed_pickup.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_NOTICE, LOG_WARNING, parse(), pickup_by_channel(), and pickup_by_part().
Referenced by load_module().
00357 { 00358 int partial_pickup = 0; 00359 char *pickup = NULL; 00360 char *parse = ast_strdupa(data); 00361 AST_DECLARE_APP_ARGS(args, 00362 AST_APP_ARG(channel); 00363 AST_APP_ARG(options); 00364 ); 00365 AST_STANDARD_APP_ARGS(args, parse); 00366 00367 if (ast_strlen_zero(args.channel)) { 00368 ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n"); 00369 /* Pickup failed. Keep going in the dialplan. */ 00370 return 0; 00371 } 00372 00373 if (!ast_strlen_zero(args.options) && strchr(args.options, 'p')) { 00374 partial_pickup = 1; 00375 } 00376 00377 /* Parse channel */ 00378 while (!ast_strlen_zero(args.channel) && (pickup = strsep(&args.channel, "&"))) { 00379 if (!strncasecmp(chan->name, pickup, strlen(pickup))) { 00380 ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup); 00381 } else { 00382 if (partial_pickup) { 00383 if (!pickup_by_part(chan, pickup)) { 00384 /* Pickup successful. Stop the dialplan this channel is a zombie. */ 00385 return -1; 00386 } 00387 } else if (!pickup_by_channel(chan, pickup)) { 00388 /* Pickup successful. Stop the dialplan this channel is a zombie. */ 00389 return -1; 00390 } 00391 ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup); 00392 } 00393 } 00394 00395 /* Pickup failed. Keep going in the dialplan. */ 00396 return 0; 00397 }
static int unload_module | ( | void | ) | [static] |
Definition at line 399 of file app_directed_pickup.c.
References ast_unregister_application().
00400 { 00401 int res; 00402 00403 res = ast_unregister_application(app); 00404 res |= ast_unregister_application(app2); 00405 00406 return res; 00407 }
const char app[] = "Pickup" [static] |
Definition at line 119 of file app_directed_pickup.c.
const char app2[] = "PickupChan" [static] |
Definition at line 120 of file app_directed_pickup.c.
Referenced by _macro_exec(), and app_cmp().