2 * Asterisk -- A telephony toolkit for Linux.
4 * feature Proxy Channel
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
16 #include "asterisk/lock.h"
17 #include "asterisk/channel.h"
18 #include "asterisk/config.h"
19 #include "asterisk/logger.h"
20 #include "asterisk/module.h"
21 #include "asterisk/pbx.h"
22 #include "asterisk/options.h"
23 #include "asterisk/lock.h"
24 #include "asterisk/sched.h"
25 #include "asterisk/io.h"
26 #include "asterisk/rtp.h"
27 #include "asterisk/acl.h"
28 #include "asterisk/callerid.h"
29 #include "asterisk/file.h"
30 #include "asterisk/cli.h"
31 #include "asterisk/app.h"
32 #include "asterisk/musiconhold.h"
33 #include "asterisk/manager.h"
34 #include <sys/socket.h>
40 #include <arpa/inet.h>
41 #include <sys/signal.h>
44 static const char desc[] = "Feature Proxy Channel";
45 static const char type[] = "Feature";
46 static const char tdesc[] = "Feature Proxy Channel Driver";
49 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
51 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
53 /* Protect the interface list (of feature_pvt's) */
54 AST_MUTEX_DEFINE_STATIC(featurelock);
57 struct ast_channel *owner;
61 int alertpipebackup[2];
64 static struct feature_pvt {
65 ast_mutex_t lock; /* Channel private lock */
66 char tech[AST_MAX_EXTENSION]; /* Technology to abstract */
67 char dest[AST_MAX_EXTENSION]; /* Destination to abstract */
68 struct ast_channel *subchan;
69 struct feature_sub subs[3]; /* Subs */
70 struct ast_channel *owner; /* Current Master Channel */
71 struct feature_pvt *next; /* Next entity */
74 #define SUB_REAL 0 /* Active call */
75 #define SUB_CALLWAIT 1 /* Call-Waiting call on hold */
76 #define SUB_THREEWAY 2 /* Three-way call */
78 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause);
79 static int features_digit(struct ast_channel *ast, char digit);
80 static int features_call(struct ast_channel *ast, char *dest, int timeout);
81 static int features_hangup(struct ast_channel *ast);
82 static int features_answer(struct ast_channel *ast);
83 static struct ast_frame *features_read(struct ast_channel *ast);
84 static int features_write(struct ast_channel *ast, struct ast_frame *f);
85 static int features_indicate(struct ast_channel *ast, int condition);
86 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
88 static const struct ast_channel_tech features_tech = {
92 .requester = features_request,
93 .send_digit = features_digit,
94 .call = features_call,
95 .hangup = features_hangup,
96 .answer = features_answer,
97 .read = features_read,
98 .write = features_write,
99 .exception = features_read,
100 .indicate = features_indicate,
101 .fixup = features_fixup,
104 static inline void init_sub(struct feature_sub *sub)
108 sub->timingfdbackup = -1;
109 sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1;
112 static inline int indexof(struct feature_pvt *p, struct ast_channel *owner, int nullok)
116 ast_log(LOG_WARNING, "indexof called on NULL owner??\n");
120 if (owner == p->subs[x].owner)
127 static void wakeup_sub(struct feature_pvt *p, int a)
129 struct ast_frame null = { AST_FRAME_NULL, };
131 if (p->subs[a].owner) {
132 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
133 ast_mutex_unlock(&p->lock);
135 ast_mutex_lock(&p->lock);
137 ast_queue_frame(p->subs[a].owner, &null);
138 ast_mutex_unlock(&p->subs[a].owner->lock);
147 static void restore_channel(struct feature_pvt *p, int index)
149 /* Restore timing/alertpipe */
150 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup;
151 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0];
152 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1];
153 p->subs[index].owner->fds[AST_MAX_FDS-1] = p->subs[index].alertpipebackup[0];
154 p->subs[index].owner->fds[AST_MAX_FDS-2] = p->subs[index].timingfdbackup;
157 static void update_features(struct feature_pvt *p, int index)
160 if (p->subs[index].owner) {
161 for (x=0;x<AST_MAX_FDS;x++) {
163 p->subs[index].owner->fds[x] = -1;
165 p->subs[index].owner->fds[x] = p->subchan->fds[x];
168 /* Copy timings from master channel */
169 p->subs[index].owner->timingfd = p->subchan->timingfd;
170 p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0];
171 p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1];
172 if (p->subs[index].owner->nativeformats != p->subchan->readformat) {
173 p->subs[index].owner->nativeformats = p->subchan->readformat;
174 if (p->subs[index].owner->readformat)
175 ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat);
176 if (p->subs[index].owner->writeformat)
177 ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat);
180 restore_channel(p, index);
186 static void swap_subs(struct feature_pvt *p, int a, int b)
189 struct ast_channel *towner;
191 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
193 towner = p->subs[a].owner;
194 tinthreeway = p->subs[a].inthreeway;
196 p->subs[a].owner = p->subs[b].owner;
197 p->subs[a].inthreeway = p->subs[b].inthreeway;
199 p->subs[b].owner = towner;
200 p->subs[b].inthreeway = tinthreeway;
201 update_features(p,a);
202 update_features(p,b);
208 static int features_answer(struct ast_channel *ast)
210 struct feature_pvt *p = ast->tech_pvt;
213 ast_mutex_lock(&p->lock);
214 x = indexof(p, ast, 0);
215 if (!x && p->subchan)
216 res = ast_answer(p->subchan);
217 ast_mutex_unlock(&p->lock);
221 static struct ast_frame *features_read(struct ast_channel *ast)
223 static struct ast_frame null_frame = { AST_FRAME_NULL, };
224 struct feature_pvt *p = ast->tech_pvt;
229 ast_mutex_lock(&p->lock);
230 x = indexof(p, ast, 0);
231 if (!x && p->subchan) {
232 update_features(p, x);
233 f = ast_read(p->subchan);
235 ast_mutex_unlock(&p->lock);
239 static int features_write(struct ast_channel *ast, struct ast_frame *f)
241 struct feature_pvt *p = ast->tech_pvt;
244 ast_mutex_lock(&p->lock);
245 x = indexof(p, ast, 0);
246 if (!x && p->subchan)
247 res = ast_write(p->subchan, f);
248 ast_mutex_unlock(&p->lock);
252 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
254 struct feature_pvt *p = newchan->tech_pvt;
256 ast_mutex_lock(&p->lock);
257 if (p->owner == oldchan)
260 if (p->subs[x].owner == oldchan)
261 p->subs[x].owner = newchan;
263 ast_mutex_unlock(&p->lock);
267 static int features_indicate(struct ast_channel *ast, int condition)
269 struct feature_pvt *p = ast->tech_pvt;
272 /* Queue up a frame representing the indication as a control frame */
273 ast_mutex_lock(&p->lock);
274 x = indexof(p, ast, 0);
275 if (!x && p->subchan)
276 res = ast_indicate(p->subchan, condition);
277 ast_mutex_unlock(&p->lock);
281 static int features_digit(struct ast_channel *ast, char digit)
283 struct feature_pvt *p = ast->tech_pvt;
286 /* Queue up a frame representing the indication as a control frame */
287 ast_mutex_lock(&p->lock);
288 x = indexof(p, ast, 0);
289 if (!x && p->subchan)
290 res = ast_senddigit(p->subchan, digit);
291 ast_mutex_unlock(&p->lock);
295 static int features_call(struct ast_channel *ast, char *dest, int timeout)
297 struct feature_pvt *p = ast->tech_pvt;
302 dest2 = strchr(dest, '/');
304 ast_mutex_lock(&p->lock);
305 x = indexof(p, ast, 0);
306 if (!x && p->subchan) {
307 if (p->owner->cid.cid_num)
308 p->subchan->cid.cid_num = strdup(p->owner->cid.cid_num);
310 p->subchan->cid.cid_num = NULL;
312 if (p->owner->cid.cid_name)
313 p->subchan->cid.cid_name = strdup(p->owner->cid.cid_name);
315 p->subchan->cid.cid_name = NULL;
317 if (p->owner->cid.cid_rdnis)
318 p->subchan->cid.cid_rdnis = strdup(p->owner->cid.cid_rdnis);
320 p->subchan->cid.cid_rdnis = NULL;
322 if (p->owner->cid.cid_ani)
323 p->subchan->cid.cid_ani = strdup(p->owner->cid.cid_ani);
325 p->subchan->cid.cid_ani = NULL;
327 strncpy(p->subchan->language, p->owner->language, sizeof(p->subchan->language) - 1);
328 strncpy(p->subchan->accountcode, p->owner->accountcode, sizeof(p->subchan->accountcode) - 1);
329 p->subchan->cdrflags = p->owner->cdrflags;
330 res = ast_call(p->subchan, dest2, timeout);
331 update_features(p, x);
333 ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n");
334 ast_mutex_unlock(&p->lock);
339 static int features_hangup(struct ast_channel *ast)
341 struct feature_pvt *p = ast->tech_pvt;
342 struct feature_pvt *cur, *prev=NULL;
345 ast_mutex_lock(&p->lock);
346 x = indexof(p, ast, 0);
348 restore_channel(p, x);
349 p->subs[x].owner = NULL;
350 /* XXX Re-arrange, unconference, etc XXX */
352 ast->tech_pvt = NULL;
355 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
356 ast_mutex_unlock(&p->lock);
357 /* Remove from list */
358 ast_mutex_lock(&featurelock);
363 prev->next = cur->next;
365 features = cur->next;
371 ast_mutex_unlock(&featurelock);
372 ast_mutex_lock(&p->lock);
375 ast_hangup(p->subchan);
376 ast_mutex_unlock(&p->lock);
377 ast_mutex_destroy(&p->lock);
381 ast_mutex_unlock(&p->lock);
385 static struct feature_pvt *features_alloc(char *data, int format)
387 struct feature_pvt *tmp;
392 struct ast_channel *chan;
394 tech = ast_strdupa(data);
396 dest = strchr(tech, '/');
402 if (!tech || !dest) {
403 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n",
407 ast_mutex_lock(&featurelock);
410 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest))
414 ast_mutex_unlock(&featurelock);
416 chan = ast_request(tech, format, dest, &status);
418 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
421 tmp = malloc(sizeof(struct feature_pvt));
423 memset(tmp, 0, sizeof(struct feature_pvt));
425 init_sub(tmp->subs + x);
426 ast_mutex_init(&tmp->lock);
427 strncpy(tmp->tech, tech, sizeof(tmp->tech) - 1);
428 strncpy(tmp->dest, dest, sizeof(tmp->dest) - 1);
430 ast_mutex_lock(&featurelock);
431 tmp->next = features;
433 ast_mutex_unlock(&featurelock);
439 static struct ast_channel *features_new(struct feature_pvt *p, int state, int index)
441 struct ast_channel *tmp;
444 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n");
447 if (p->subs[index].owner) {
448 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index);
451 tmp = ast_channel_alloc(0);
455 tmp->tech = &features_tech;
457 snprintf(tmp->name, sizeof(tmp->name), "Feature/%s/%s-%d", p->tech, p->dest, x);
461 if (p->subs[x].owner && !strcasecmp(p->subs[x].owner->name, tmp->name))
468 ast_setstate(tmp, state);
469 tmp->writeformat = p->subchan->writeformat;
470 tmp->rawwriteformat = p->subchan->rawwriteformat;
471 tmp->readformat = p->subchan->readformat;
472 tmp->rawreadformat = p->subchan->rawreadformat;
473 tmp->nativeformats = p->subchan->readformat;
475 p->subs[index].owner = tmp;
478 ast_mutex_lock(&usecnt_lock);
480 ast_mutex_unlock(&usecnt_lock);
481 ast_update_use_count();
483 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
488 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause)
490 struct feature_pvt *p;
491 struct ast_channel *chan = NULL;
492 p = features_alloc(data, format);
493 if (p && !p->subs[SUB_REAL].owner)
494 chan = features_new(p, AST_STATE_DOWN, SUB_REAL);
496 update_features(p,SUB_REAL);
500 static int features_show(int fd, int argc, char **argv)
502 struct feature_pvt *p;
505 return RESULT_SHOWUSAGE;
506 ast_mutex_lock(&featurelock);
509 ast_mutex_lock(&p->lock);
510 ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest);
511 ast_mutex_unlock(&p->lock);
515 ast_cli(fd, "No feature channels in use\n");
516 ast_mutex_unlock(&featurelock);
517 return RESULT_SUCCESS;
520 static char show_features_usage[] =
521 "Usage: feature show channels\n"
522 " Provides summary information on feature channels.\n";
524 static struct ast_cli_entry cli_show_features = {
525 { "feature", "show", "channels", NULL }, features_show,
526 "Show status of feature channels", show_features_usage, NULL };
530 /* Make sure we can register our sip channel type */
531 if (ast_channel_register(&features_tech)) {
532 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
535 ast_cli_register(&cli_show_features);
546 struct feature_pvt *p;
547 /* First, take us out of the channel loop */
548 ast_cli_unregister(&cli_show_features);
549 ast_channel_unregister(&features_tech);
550 if (!ast_mutex_lock(&featurelock)) {
551 /* Hangup all interfaces if they have an owner */
555 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
559 ast_mutex_unlock(&featurelock);
561 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
570 ast_mutex_lock(&usecnt_lock);
572 ast_mutex_unlock(&usecnt_lock);
578 return ASTERISK_GPL_KEY;
583 return (char *) desc;