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