00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 160228 $")
00036
00037 #include <fcntl.h>
00038 #include <sys/signal.h>
00039
00040 #include "asterisk/lock.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/config.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/sched.h"
00046 #include "asterisk/io.h"
00047 #include "asterisk/rtp.h"
00048 #include "asterisk/acl.h"
00049 #include "asterisk/callerid.h"
00050 #include "asterisk/file.h"
00051 #include "asterisk/cli.h"
00052 #include "asterisk/app.h"
00053 #include "asterisk/musiconhold.h"
00054 #include "asterisk/manager.h"
00055 #include "asterisk/stringfields.h"
00056
00057 static const char tdesc[] = "Feature Proxy Channel Driver";
00058
00059 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
00060
00061 struct feature_sub {
00062 struct ast_channel *owner;
00063 int inthreeway;
00064 int pfd;
00065 int timingfdbackup;
00066 int alertpipebackup[2];
00067 };
00068
00069 struct feature_pvt {
00070 ast_mutex_t lock;
00071 char tech[AST_MAX_EXTENSION];
00072 char dest[AST_MAX_EXTENSION];
00073 struct ast_channel *subchan;
00074 struct feature_sub subs[3];
00075 struct ast_channel *owner;
00076 AST_LIST_ENTRY(feature_pvt) list;
00077 };
00078
00079 static AST_LIST_HEAD_STATIC(features, feature_pvt);
00080
00081 #define SUB_REAL 0
00082 #define SUB_CALLWAIT 1
00083 #define SUB_THREEWAY 2
00084
00085 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause);
00086 static int features_digit_begin(struct ast_channel *ast, char digit);
00087 static int features_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00088 static int features_call(struct ast_channel *ast, char *dest, int timeout);
00089 static int features_hangup(struct ast_channel *ast);
00090 static int features_answer(struct ast_channel *ast);
00091 static struct ast_frame *features_read(struct ast_channel *ast);
00092 static int features_write(struct ast_channel *ast, struct ast_frame *f);
00093 static int features_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
00094 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00095
00096 static const struct ast_channel_tech features_tech = {
00097 .type = "Feature",
00098 .description = tdesc,
00099 .capabilities = -1,
00100 .requester = features_request,
00101 .send_digit_begin = features_digit_begin,
00102 .send_digit_end = features_digit_end,
00103 .call = features_call,
00104 .hangup = features_hangup,
00105 .answer = features_answer,
00106 .read = features_read,
00107 .write = features_write,
00108 .exception = features_read,
00109 .indicate = features_indicate,
00110 .fixup = features_fixup,
00111 };
00112
00113 static inline void init_sub(struct feature_sub *sub)
00114 {
00115 sub->inthreeway = 0;
00116 sub->pfd = -1;
00117 sub->timingfdbackup = -1;
00118 sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1;
00119 }
00120
00121 static inline int indexof(struct feature_pvt *p, struct ast_channel *owner, int nullok)
00122 {
00123 int x;
00124 if (!owner) {
00125 ast_log(LOG_WARNING, "indexof called on NULL owner??\n");
00126 return -1;
00127 }
00128 for (x=0; x<3; x++) {
00129 if (owner == p->subs[x].owner)
00130 return x;
00131 }
00132 return -1;
00133 }
00134
00135 #if 0
00136 static void wakeup_sub(struct feature_pvt *p, int a)
00137 {
00138 struct ast_frame null = { AST_FRAME_NULL, };
00139 for (;;) {
00140 if (p->subs[a].owner) {
00141 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
00142 ast_mutex_unlock(&p->lock);
00143 usleep(1);
00144 ast_mutex_lock(&p->lock);
00145 } else {
00146 ast_queue_frame(p->subs[a].owner, &null);
00147 ast_mutex_unlock(&p->subs[a].owner->lock);
00148 break;
00149 }
00150 } else
00151 break;
00152 }
00153 }
00154 #endif
00155
00156 static void restore_channel(struct feature_pvt *p, int index)
00157 {
00158
00159 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup;
00160 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0];
00161 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1];
00162 ast_channel_set_fd(p->subs[index].owner, AST_ALERT_FD, p->subs[index].alertpipebackup[0]);
00163 ast_channel_set_fd(p->subs[index].owner, AST_TIMING_FD, p->subs[index].timingfdbackup);
00164 }
00165
00166 static void update_features(struct feature_pvt *p, int index)
00167 {
00168 int x;
00169 if (p->subs[index].owner) {
00170 for (x=0; x<AST_MAX_FDS; x++) {
00171 if (index)
00172 ast_channel_set_fd(p->subs[index].owner, x, -1);
00173 else
00174 ast_channel_set_fd(p->subs[index].owner, x, p->subchan->fds[x]);
00175 }
00176 if (!index) {
00177
00178 p->subs[index].owner->timingfd = p->subchan->timingfd;
00179 p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0];
00180 p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1];
00181 if (p->subs[index].owner->nativeformats != p->subchan->readformat) {
00182 p->subs[index].owner->nativeformats = p->subchan->readformat;
00183 if (p->subs[index].owner->readformat)
00184 ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat);
00185 if (p->subs[index].owner->writeformat)
00186 ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat);
00187 }
00188 } else{
00189 restore_channel(p, index);
00190 }
00191 }
00192 }
00193
00194 #if 0
00195 static void swap_subs(struct feature_pvt *p, int a, int b)
00196 {
00197 int tinthreeway;
00198 struct ast_channel *towner;
00199
00200 ast_debug(1, "Swapping %d and %d\n", a, b);
00201
00202 towner = p->subs[a].owner;
00203 tinthreeway = p->subs[a].inthreeway;
00204
00205 p->subs[a].owner = p->subs[b].owner;
00206 p->subs[a].inthreeway = p->subs[b].inthreeway;
00207
00208 p->subs[b].owner = towner;
00209 p->subs[b].inthreeway = tinthreeway;
00210 update_features(p,a);
00211 update_features(p,b);
00212 wakeup_sub(p, a);
00213 wakeup_sub(p, b);
00214 }
00215 #endif
00216
00217 static int features_answer(struct ast_channel *ast)
00218 {
00219 struct feature_pvt *p = ast->tech_pvt;
00220 int res = -1;
00221 int x;
00222
00223 ast_mutex_lock(&p->lock);
00224 x = indexof(p, ast, 0);
00225 if (!x && p->subchan)
00226 res = ast_answer(p->subchan);
00227 ast_mutex_unlock(&p->lock);
00228 return res;
00229 }
00230
00231 static struct ast_frame *features_read(struct ast_channel *ast)
00232 {
00233 struct feature_pvt *p = ast->tech_pvt;
00234 struct ast_frame *f;
00235 int x;
00236
00237 f = &ast_null_frame;
00238 ast_mutex_lock(&p->lock);
00239 x = indexof(p, ast, 0);
00240 if (!x && p->subchan) {
00241 update_features(p, x);
00242 f = ast_read(p->subchan);
00243 }
00244 ast_mutex_unlock(&p->lock);
00245 return f;
00246 }
00247
00248 static int features_write(struct ast_channel *ast, struct ast_frame *f)
00249 {
00250 struct feature_pvt *p = ast->tech_pvt;
00251 int res = -1;
00252 int x;
00253
00254 ast_mutex_lock(&p->lock);
00255 x = indexof(p, ast, 0);
00256 if (!x && p->subchan)
00257 res = ast_write(p->subchan, f);
00258 ast_mutex_unlock(&p->lock);
00259 return res;
00260 }
00261
00262 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00263 {
00264 struct feature_pvt *p = newchan->tech_pvt;
00265 int x;
00266
00267 ast_mutex_lock(&p->lock);
00268 if (p->owner == oldchan)
00269 p->owner = newchan;
00270 for (x = 0; x < 3; x++) {
00271 if (p->subs[x].owner == oldchan)
00272 p->subs[x].owner = newchan;
00273 }
00274 ast_mutex_unlock(&p->lock);
00275 return 0;
00276 }
00277
00278 static int features_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
00279 {
00280 struct feature_pvt *p = ast->tech_pvt;
00281 int res = -1;
00282 int x;
00283
00284
00285 ast_mutex_lock(&p->lock);
00286 x = indexof(p, ast, 0);
00287 if (!x && p->subchan)
00288 res = ast_indicate(p->subchan, condition);
00289 ast_mutex_unlock(&p->lock);
00290 return res;
00291 }
00292
00293 static int features_digit_begin(struct ast_channel *ast, char digit)
00294 {
00295 struct feature_pvt *p = ast->tech_pvt;
00296 int res = -1;
00297 int x;
00298
00299
00300 ast_mutex_lock(&p->lock);
00301 x = indexof(p, ast, 0);
00302 if (!x && p->subchan)
00303 res = ast_senddigit_begin(p->subchan, digit);
00304 ast_mutex_unlock(&p->lock);
00305
00306 return res;
00307 }
00308
00309 static int features_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
00310 {
00311 struct feature_pvt *p = ast->tech_pvt;
00312 int res = -1;
00313 int x;
00314
00315
00316 ast_mutex_lock(&p->lock);
00317 x = indexof(p, ast, 0);
00318 if (!x && p->subchan)
00319 res = ast_senddigit_end(p->subchan, digit, duration);
00320 ast_mutex_unlock(&p->lock);
00321 return res;
00322 }
00323
00324 static int features_call(struct ast_channel *ast, char *dest, int timeout)
00325 {
00326 struct feature_pvt *p = ast->tech_pvt;
00327 int res = -1;
00328 int x;
00329 char *dest2;
00330
00331 dest2 = strchr(dest, '/');
00332 if (dest2) {
00333 ast_mutex_lock(&p->lock);
00334 x = indexof(p, ast, 0);
00335 if (!x && p->subchan) {
00336 p->subchan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
00337 p->subchan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
00338 p->subchan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
00339 p->subchan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
00340
00341 p->subchan->cid.cid_pres = p->owner->cid.cid_pres;
00342 ast_string_field_set(p->subchan, language, p->owner->language);
00343 ast_string_field_set(p->subchan, accountcode, p->owner->accountcode);
00344 p->subchan->cdrflags = p->owner->cdrflags;
00345 res = ast_call(p->subchan, dest2, timeout);
00346 update_features(p, x);
00347 } else
00348 ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n");
00349 ast_mutex_unlock(&p->lock);
00350 }
00351 return res;
00352 }
00353
00354 static int features_hangup(struct ast_channel *ast)
00355 {
00356 struct feature_pvt *p = ast->tech_pvt;
00357 int x;
00358
00359 ast_mutex_lock(&p->lock);
00360 x = indexof(p, ast, 0);
00361 if (x > -1) {
00362 restore_channel(p, x);
00363 p->subs[x].owner = NULL;
00364
00365 }
00366 ast->tech_pvt = NULL;
00367
00368 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
00369 ast_mutex_unlock(&p->lock);
00370
00371 AST_LIST_LOCK(&features);
00372 AST_LIST_REMOVE(&features, p, list);
00373 AST_LIST_UNLOCK(&features);
00374 ast_mutex_lock(&p->lock);
00375
00376 if (p->subchan)
00377 ast_hangup(p->subchan);
00378 ast_mutex_unlock(&p->lock);
00379 ast_mutex_destroy(&p->lock);
00380 ast_free(p);
00381 return 0;
00382 }
00383 ast_mutex_unlock(&p->lock);
00384 return 0;
00385 }
00386
00387 static struct feature_pvt *features_alloc(char *data, int format)
00388 {
00389 struct feature_pvt *tmp;
00390 char *dest=NULL;
00391 char *tech;
00392 int x;
00393 int status;
00394 struct ast_channel *chan;
00395
00396 tech = ast_strdupa(data);
00397 if (tech) {
00398 dest = strchr(tech, '/');
00399 if (dest) {
00400 *dest = '\0';
00401 dest++;
00402 }
00403 }
00404 if (!tech || !dest) {
00405 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n",
00406 data);
00407 return NULL;
00408 }
00409 AST_LIST_LOCK(&features);
00410 AST_LIST_TRAVERSE(&features, tmp, list) {
00411 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest))
00412 break;
00413 }
00414 AST_LIST_UNLOCK(&features);
00415 if (!tmp) {
00416 chan = ast_request(tech, format, dest, &status);
00417 if (!chan) {
00418 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
00419 return NULL;
00420 }
00421 tmp = ast_calloc(1, sizeof(*tmp));
00422 if (tmp) {
00423 for (x=0;x<3;x++)
00424 init_sub(tmp->subs + x);
00425 ast_mutex_init(&tmp->lock);
00426 ast_copy_string(tmp->tech, tech, sizeof(tmp->tech));
00427 ast_copy_string(tmp->dest, dest, sizeof(tmp->dest));
00428 tmp->subchan = chan;
00429 AST_LIST_LOCK(&features);
00430 AST_LIST_INSERT_HEAD(&features, tmp, list);
00431 AST_LIST_UNLOCK(&features);
00432 }
00433 }
00434 return tmp;
00435 }
00436
00437 static struct ast_channel *features_new(struct feature_pvt *p, int state, int index)
00438 {
00439 struct ast_channel *tmp;
00440 int x,y;
00441 char *b2 = 0;
00442 if (!p->subchan) {
00443 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n");
00444 return NULL;
00445 }
00446 if (p->subs[index].owner) {
00447 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index);
00448 return NULL;
00449 }
00450
00451 for (x=1;x<4;x++) {
00452 if (b2)
00453 ast_free(b2);
00454 if (asprintf(&b2, "%s/%s-%d", p->tech, p->dest, x) < 0) {
00455 ast_log(LOG_WARNING, "Unable to create channel name: %s\n", strerror(errno));
00456 b2 = NULL;
00457 continue;
00458 }
00459 for (y=0;y<3;y++) {
00460 if (y == index)
00461 continue;
00462 if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, b2))
00463 break;
00464 }
00465 if (y >= 3)
00466 break;
00467 }
00468 tmp = ast_channel_alloc(0, state, 0,0, "", "", "", 0, "Feature/%s", b2);
00469
00470 if (b2)
00471 ast_free(b2);
00472 if (!tmp) {
00473 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00474 return NULL;
00475 }
00476 tmp->tech = &features_tech;
00477 tmp->writeformat = p->subchan->writeformat;
00478 tmp->rawwriteformat = p->subchan->rawwriteformat;
00479 tmp->readformat = p->subchan->readformat;
00480 tmp->rawreadformat = p->subchan->rawreadformat;
00481 tmp->nativeformats = p->subchan->readformat;
00482 tmp->tech_pvt = p;
00483 p->subs[index].owner = tmp;
00484 if (!p->owner)
00485 p->owner = tmp;
00486 ast_module_ref(ast_module_info->self);
00487 return tmp;
00488 }
00489
00490
00491 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause)
00492 {
00493 struct feature_pvt *p;
00494 struct ast_channel *chan = NULL;
00495
00496 p = features_alloc(data, format);
00497 if (p && !p->subs[SUB_REAL].owner)
00498 chan = features_new(p, AST_STATE_DOWN, SUB_REAL);
00499 if (chan)
00500 update_features(p,SUB_REAL);
00501 return chan;
00502 }
00503
00504 static char *features_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00505 {
00506 struct feature_pvt *p;
00507
00508 switch (cmd) {
00509 case CLI_INIT:
00510 e->command = "feature show channels";
00511 e->usage =
00512 "Usage: feature show channels\n"
00513 " Provides summary information on feature channels.\n";
00514 return NULL;
00515 case CLI_GENERATE:
00516 return NULL;
00517 }
00518
00519 if (a->argc != 3)
00520 return CLI_SHOWUSAGE;
00521
00522 if (AST_LIST_EMPTY(&features)) {
00523 ast_cli(a->fd, "No feature channels in use\n");
00524 return CLI_SUCCESS;
00525 }
00526
00527 AST_LIST_LOCK(&features);
00528 AST_LIST_TRAVERSE(&features, p, list) {
00529 ast_mutex_lock(&p->lock);
00530 ast_cli(a->fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest);
00531 ast_mutex_unlock(&p->lock);
00532 }
00533 AST_LIST_UNLOCK(&features);
00534 return CLI_SUCCESS;
00535 }
00536
00537 static struct ast_cli_entry cli_features[] = {
00538 AST_CLI_DEFINE(features_show, "List status of feature channels"),
00539 };
00540
00541 static int load_module(void)
00542 {
00543
00544 if (ast_channel_register(&features_tech)) {
00545 ast_log(LOG_ERROR, "Unable to register channel class 'Feature'\n");
00546 return AST_MODULE_LOAD_FAILURE;
00547 }
00548 ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
00549 return AST_MODULE_LOAD_SUCCESS;
00550 }
00551
00552 static int unload_module(void)
00553 {
00554 struct feature_pvt *p;
00555
00556
00557 ast_cli_unregister_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
00558 ast_channel_unregister(&features_tech);
00559
00560 if (!AST_LIST_LOCK(&features))
00561 return -1;
00562
00563 while ((p = AST_LIST_REMOVE_HEAD(&features, list))) {
00564 if (p->owner)
00565 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
00566 ast_free(p);
00567 }
00568 AST_LIST_UNLOCK(&features);
00569
00570 return 0;
00571 }
00572
00573 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Feature Proxy Channel");
00574