#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 | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | can_pickup (struct ast_channel *chan) |
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 | 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 specified channel named , does not use context. | |
static int | pickup_by_exten (struct ast_channel *chan, const char *exten, const char *context) |
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_do (struct ast_channel *chan, struct ast_channel *target) |
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 struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Directed Call Pickup Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
static const char | app [] = "Pickup" |
static const char | app2 [] = "PickupChan" |
static struct ast_module_info * | ast_module_info = &__mod_info |
Gary Cook
Definition in file app_directed_pickup.c.
#define PICKUPMARK "PICKUPMARK" |
Definition at line 47 of file app_directed_pickup.c.
Referenced by find_by_mark(), and pickup_exec().
static void __reg_module | ( | void | ) | [static] |
Definition at line 413 of file app_directed_pickup.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 413 of file app_directed_pickup.c.
static int can_pickup | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 148 of file app_directed_pickup.c.
References ast_channel::_state, AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, and ast_channel::pbx.
Referenced by find_by_mark(), find_by_part(), pickup_by_exten(), and pickup_by_name_cb().
00149 { 00150 if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN)) 00151 return 1; 00152 else 00153 return 0; 00154 }
static int find_by_mark | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 256 of file app_directed_pickup.c.
References ast_channel_lock, ast_channel_unlock, can_pickup(), CMP_MATCH, CMP_STOP, pbx_builtin_getvar_helper(), and PICKUPMARK.
Referenced by pickup_by_mark().
00257 { 00258 struct ast_channel *c = obj; 00259 const char *mark = data; 00260 const char *tmp; 00261 int res; 00262 00263 ast_channel_lock(c); 00264 00265 res = (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) && 00266 !strcasecmp(tmp, mark) && 00267 can_pickup(c); 00268 00269 ast_channel_unlock(c); 00270 00271 return res ? CMP_MATCH | CMP_STOP : 0; 00272 }
static int find_by_part | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 320 of file app_directed_pickup.c.
References ast_channel_lock, ast_channel_unlock, can_pickup(), CMP_MATCH, CMP_STOP, len(), and ast_channel::name.
Referenced by pickup_by_part().
00321 { 00322 struct ast_channel *c = obj; 00323 const char *part = data; 00324 int res = 0; 00325 int len = strlen(part); 00326 00327 ast_channel_lock(c); 00328 if (len <= strlen(c->name)) { 00329 res = !(strncmp(c->name, part, len)) && (can_pickup(c)); 00330 } 00331 ast_channel_unlock(c); 00332 00333 return res ? CMP_MATCH | CMP_STOP : 0; 00334 }
static int load_module | ( | void | ) | [static] |
Definition at line 403 of file app_directed_pickup.c.
References ast_register_application_xml, pickup_exec(), and pickupchan_exec().
00404 { 00405 int res; 00406 00407 res = ast_register_application_xml(app, pickup_exec); 00408 res |= ast_register_application_xml(app2, pickupchan_exec); 00409 00410 return res; 00411 }
static struct ast_channel* my_ast_get_channel_by_name_locked | ( | const char * | channame | ) | [static] |
Helper Function to walk through ALL channels checking NAME and STATE.
Definition at line 177 of file app_directed_pickup.c.
References ast_channel_callback(), pickup_by_name_args::len, pickup_by_name_args::name, and pickup_by_name_cb().
Referenced by pickup_by_channel().
00178 { 00179 char *chkchan; 00180 struct pickup_by_name_args pickup_args; 00181 00182 /* Check if channel name contains a '-'. 00183 * In this case the channel name will be interpreted as full channel name. 00184 */ 00185 if (strchr(channame, '-')) { 00186 /* check full channel name */ 00187 pickup_args.len = strlen(channame); 00188 pickup_args.name = channame; 00189 } else { 00190 /* need to append a '-' for the comparison so we check full channel name, 00191 * i.e SIP/hgc- , use a temporary variable so original stays the same for 00192 * debugging. 00193 */ 00194 pickup_args.len = strlen(channame) + 1; 00195 chkchan = alloca(pickup_args.len + 1); 00196 strcpy(chkchan, channame); 00197 strcat(chkchan, "-"); 00198 pickup_args.name = chkchan; 00199 } 00200 00201 return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0); 00202 }
static int pickup_by_channel | ( | struct ast_channel * | chan, | |
char * | pickup | |||
) | [static] |
Attempt to pick up specified channel named , does not use context.
Definition at line 205 of file app_directed_pickup.c.
References ast_channel_unlock, ast_channel_unref, my_ast_get_channel_by_name_locked(), and pickup_do().
Referenced by pickupchan_exec().
00206 { 00207 int res = 0; 00208 struct ast_channel *target; 00209 00210 if (!(target = my_ast_get_channel_by_name_locked(pickup))) { 00211 return -1; 00212 } 00213 00214 /* Just check that we are not picking up the SAME as target */ 00215 if (chan != target) { 00216 res = pickup_do(chan, target); 00217 } 00218 00219 ast_channel_unlock(target); 00220 target = ast_channel_unref(target); 00221 00222 return res; 00223 }
static int pickup_by_exten | ( | struct ast_channel * | chan, | |
const char * | exten, | |||
const char * | context | |||
) | [static] |
Definition at line 226 of file app_directed_pickup.c.
References ast_channel_iterator_by_exten_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, can_pickup(), and pickup_do().
Referenced by pickup_exec().
00227 { 00228 struct ast_channel *target = NULL; 00229 struct ast_channel_iterator *iter; 00230 int res = -1; 00231 00232 if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) { 00233 return -1; 00234 } 00235 00236 while ((target = ast_channel_iterator_next(iter))) { 00237 ast_channel_lock(target); 00238 if ((chan != target) && can_pickup(target)) { 00239 break; 00240 } 00241 ast_channel_unlock(target); 00242 target = ast_channel_unref(target); 00243 } 00244 00245 ast_channel_iterator_destroy(iter); 00246 00247 if (target) { 00248 res = pickup_do(chan, target); 00249 ast_channel_unlock(target); 00250 target = ast_channel_unref(target); 00251 } 00252 00253 return res; 00254 }
static int pickup_by_mark | ( | struct ast_channel * | chan, | |
const char * | mark | |||
) | [static] |
Definition at line 275 of file app_directed_pickup.c.
References ast_channel_callback(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, find_by_mark(), and pickup_do().
Referenced by pickup_exec().
00276 { 00277 struct ast_channel *target; 00278 int res = -1; 00279 00280 if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) { 00281 ast_channel_lock(target); 00282 res = pickup_do(chan, target); 00283 ast_channel_unlock(target); 00284 target = ast_channel_unref(target); 00285 } 00286 00287 return res; 00288 }
static int pickup_by_name_cb | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 161 of file app_directed_pickup.c.
References args, ast_channel_lock, ast_channel_unlock, can_pickup(), CMP_MATCH, CMP_STOP, and ast_channel::name.
Referenced by my_ast_get_channel_by_name_locked().
00162 { 00163 struct ast_channel *chan = obj; 00164 struct pickup_by_name_args *args = data; 00165 00166 ast_channel_lock(chan); 00167 if (!strncasecmp(chan->name, args->name, args->len) && can_pickup(chan)) { 00168 /* Return with the channel still locked on purpose */ 00169 return CMP_MATCH | CMP_STOP; 00170 } 00171 ast_channel_unlock(chan); 00172 00173 return 0; 00174 }
static int pickup_by_part | ( | struct ast_channel * | chan, | |
const char * | part | |||
) | [static] |
Definition at line 337 of file app_directed_pickup.c.
References ast_channel_callback(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, find_by_part(), and pickup_do().
Referenced by pickupchan_exec().
00338 { 00339 struct ast_channel *target; 00340 int res = -1; 00341 00342 if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) { 00343 ast_channel_lock(target); 00344 res = pickup_do(chan, target); 00345 ast_channel_unlock(target); 00346 target = ast_channel_unref(target); 00347 } 00348 00349 return res; 00350 }
static int pickup_do | ( | struct ast_channel * | chan, | |
struct ast_channel * | target | |||
) | [static] |
Definition at line 101 of file app_directed_pickup.c.
References ast_answer(), AST_CEL_PICKUP, ast_cel_report_event(), ast_channel_connected_line_macro(), ast_channel_lock, ast_channel_masquerade(), ast_channel_queue_connected_line_update(), ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_manager_event_multichan, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_queue_control(), ast_channel::caller, EVENT_FLAG_CALL, LOG_WARNING, ast_channel::name, and ast_party_connected_line::source.
Referenced by pickup_by_channel(), pickup_by_exten(), pickup_by_mark(), and pickup_by_part().
00102 { 00103 int res = 0; 00104 struct ast_party_connected_line connected_caller; 00105 struct ast_channel *chans[2] = { chan, target }; 00106 00107 ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name); 00108 ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan); 00109 00110 ast_party_connected_line_init(&connected_caller); 00111 ast_party_connected_line_copy(&connected_caller, &target->connected); 00112 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 00113 if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) { 00114 ast_channel_update_connected_line(chan, &connected_caller, NULL); 00115 } 00116 ast_party_connected_line_free(&connected_caller); 00117 00118 ast_channel_lock(chan); 00119 ast_connected_line_copy_from_caller(&connected_caller, &chan->caller); 00120 ast_channel_unlock(chan); 00121 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 00122 ast_channel_queue_connected_line_update(chan, &connected_caller, NULL); 00123 ast_party_connected_line_free(&connected_caller); 00124 00125 if ((res = ast_answer(chan))) { 00126 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); 00127 return -1; 00128 } 00129 00130 if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) { 00131 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); 00132 return -1; 00133 } 00134 00135 if ((res = ast_channel_masquerade(target, chan))) { 00136 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name); 00137 return -1; 00138 } 00139 00140 /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */ 00141 ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans, 00142 "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, target->name); 00143 00144 return res; 00145 }
static int pickup_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 291 of file app_directed_pickup.c.
References ast_log(), ast_pickup_call(), ast_strdupa, ast_strlen_zero(), ast_channel::context, context, exten, LOG_NOTICE, pickup_by_exten(), pickup_by_mark(), PICKUPMARK, and strsep().
Referenced by load_module().
00292 { 00293 int res = 0; 00294 char *tmp = ast_strdupa(data); 00295 char *exten = NULL, *context = NULL; 00296 00297 if (ast_strlen_zero(data)) { 00298 res = ast_pickup_call(chan); 00299 return res; 00300 } 00301 00302 /* Parse extension (and context if there) */ 00303 while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) { 00304 if ((context = strchr(exten, '@'))) 00305 *context++ = '\0'; 00306 if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) { 00307 if (!pickup_by_mark(chan, exten)) 00308 break; 00309 } else { 00310 if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context)) 00311 break; 00312 } 00313 ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten); 00314 } 00315 00316 return res; 00317 }
static int pickupchan_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 353 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, ast_channel::name, parse(), pickup_by_channel(), pickup_by_part(), and strsep().
Referenced by load_module().
00354 { 00355 int res = 0; 00356 int partial_pickup = 0; 00357 char *pickup = NULL; 00358 char *parse = ast_strdupa(data); 00359 AST_DECLARE_APP_ARGS(args, 00360 AST_APP_ARG(channel); 00361 AST_APP_ARG(options); 00362 ); 00363 AST_STANDARD_APP_ARGS(args, parse); 00364 00365 if (ast_strlen_zero(args.channel)) { 00366 ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n"); 00367 return -1; 00368 } 00369 00370 if (!ast_strlen_zero(args.options) && strchr(args.options, 'p')) { 00371 partial_pickup = 1; 00372 } 00373 00374 /* Parse channel */ 00375 while (!ast_strlen_zero(args.channel) && (pickup = strsep(&args.channel, "&"))) { 00376 if (!strncasecmp(chan->name, pickup, strlen(pickup))) { 00377 ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup); 00378 } else { 00379 if (partial_pickup) { 00380 if (!pickup_by_part(chan, pickup)) { 00381 break; 00382 } 00383 } else if (!pickup_by_channel(chan, pickup)) { 00384 break; 00385 } 00386 ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup); 00387 } 00388 } 00389 00390 return res; 00391 }
static int unload_module | ( | void | ) | [static] |
Definition at line 393 of file app_directed_pickup.c.
References ast_unregister_application().
00394 { 00395 int res; 00396 00397 res = ast_unregister_application(app); 00398 res |= ast_unregister_application(app2); 00399 00400 return res; 00401 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Directed Call Pickup Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 413 of file app_directed_pickup.c.
const char app[] = "Pickup" [static] |
Definition at line 96 of file app_directed_pickup.c.
const char app2[] = "PickupChan" [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 413 of file app_directed_pickup.c.