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)
126 static void wakeup_sub(struct feature_pvt *p, int a)
128 struct ast_frame null = { AST_FRAME_NULL, };
130 if (p->subs[a].owner) {
131 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
132 ast_mutex_unlock(&p->lock);
134 ast_mutex_lock(&p->lock);
136 ast_queue_frame(p->subs[a].owner, &null);
137 ast_mutex_unlock(&p->subs[a].owner->lock);
145 static void restore_channel(struct feature_pvt *p, int index)
147 /* Restore timing/alertpipe */
148 p->subs[index].owner->timingfd = p->subs[index].timingfdbackup;
149 p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0];
150 p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1];
151 p->subs[index].owner->fds[AST_MAX_FDS-1] = p->subs[index].alertpipebackup[0];
152 p->subs[index].owner->fds[AST_MAX_FDS-2] = p->subs[index].timingfdbackup;
155 static void update_features(struct feature_pvt *p, int index)
158 if (p->subs[index].owner) {
159 for (x=0;x<AST_MAX_FDS;x++) {
161 p->subs[index].owner->fds[x] = -1;
163 p->subs[index].owner->fds[x] = p->subchan->fds[x];
166 /* Copy timings from master channel */
167 p->subs[index].owner->timingfd = p->subchan->timingfd;
168 p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0];
169 p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1];
170 if (p->subs[index].owner->nativeformats != p->subchan->readformat) {
171 p->subs[index].owner->nativeformats = p->subchan->readformat;
172 if (p->subs[index].owner->readformat)
173 ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat);
174 if (p->subs[index].owner->writeformat)
175 ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat);
178 restore_channel(p, index);
183 static void swap_subs(struct feature_pvt *p, int a, int b)
186 struct ast_channel *towner;
188 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
190 towner = p->subs[a].owner;
191 tinthreeway = p->subs[a].inthreeway;
193 p->subs[a].owner = p->subs[b].owner;
194 p->subs[a].inthreeway = p->subs[b].inthreeway;
196 p->subs[b].owner = towner;
197 p->subs[b].inthreeway = tinthreeway;
198 update_features(p,a);
199 update_features(p,b);
204 static int features_answer(struct ast_channel *ast)
206 struct feature_pvt *p = ast->tech_pvt;
209 ast_mutex_lock(&p->lock);
210 x = indexof(p, ast, 0);
211 if (!x && p->subchan)
212 res = ast_answer(p->subchan);
213 ast_mutex_unlock(&p->lock);
217 static struct ast_frame *features_read(struct ast_channel *ast)
219 static struct ast_frame null_frame = { AST_FRAME_NULL, };
220 struct feature_pvt *p = ast->tech_pvt;
225 ast_mutex_lock(&p->lock);
226 x = indexof(p, ast, 0);
227 if (!x && p->subchan) {
228 update_features(p, x);
229 f = ast_read(p->subchan);
231 ast_mutex_unlock(&p->lock);
235 static int features_write(struct ast_channel *ast, struct ast_frame *f)
237 struct feature_pvt *p = ast->tech_pvt;
240 ast_mutex_lock(&p->lock);
241 x = indexof(p, ast, 0);
242 if (!x && p->subchan)
243 res = ast_write(p->subchan, f);
244 ast_mutex_unlock(&p->lock);
248 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
250 struct feature_pvt *p = newchan->tech_pvt;
252 ast_mutex_lock(&p->lock);
253 if (p->owner == oldchan)
256 if (p->subs[x].owner == oldchan)
257 p->subs[x].owner = newchan;
259 ast_mutex_unlock(&p->lock);
263 static int features_indicate(struct ast_channel *ast, int condition)
265 struct feature_pvt *p = ast->tech_pvt;
268 /* Queue up a frame representing the indication as a control frame */
269 ast_mutex_lock(&p->lock);
270 x = indexof(p, ast, 0);
271 if (!x && p->subchan)
272 res = ast_indicate(p->subchan, condition);
273 ast_mutex_unlock(&p->lock);
277 static int features_digit(struct ast_channel *ast, char digit)
279 struct feature_pvt *p = ast->tech_pvt;
282 /* Queue up a frame representing the indication as a control frame */
283 ast_mutex_lock(&p->lock);
284 x = indexof(p, ast, 0);
285 if (!x && p->subchan)
286 res = ast_senddigit(p->subchan, digit);
287 ast_mutex_unlock(&p->lock);
291 static int features_call(struct ast_channel *ast, char *dest, int timeout)
293 struct feature_pvt *p = ast->tech_pvt;
298 dest2 = strchr(dest, '/');
300 ast_mutex_lock(&p->lock);
301 x = indexof(p, ast, 0);
302 if (!x && p->subchan) {
303 if (p->owner->cid.cid_num)
304 p->subchan->cid.cid_num = strdup(p->owner->cid.cid_num);
306 p->subchan->cid.cid_num = NULL;
308 if (p->owner->cid.cid_name)
309 p->subchan->cid.cid_name = strdup(p->owner->cid.cid_name);
311 p->subchan->cid.cid_name = NULL;
313 if (p->owner->cid.cid_rdnis)
314 p->subchan->cid.cid_rdnis = strdup(p->owner->cid.cid_rdnis);
316 p->subchan->cid.cid_rdnis = NULL;
318 if (p->owner->cid.cid_ani)
319 p->subchan->cid.cid_ani = strdup(p->owner->cid.cid_ani);
321 p->subchan->cid.cid_ani = NULL;
323 strncpy(p->subchan->language, p->owner->language, sizeof(p->subchan->language) - 1);
324 strncpy(p->subchan->accountcode, p->owner->accountcode, sizeof(p->subchan->accountcode) - 1);
325 p->subchan->cdrflags = p->owner->cdrflags;
326 res = ast_call(p->subchan, dest2, timeout);
327 update_features(p, x);
329 ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n");
330 ast_mutex_unlock(&p->lock);
335 static int features_hangup(struct ast_channel *ast)
337 struct feature_pvt *p = ast->tech_pvt;
338 struct feature_pvt *cur, *prev=NULL;
341 ast_mutex_lock(&p->lock);
342 x = indexof(p, ast, 0);
344 restore_channel(p, x);
345 p->subs[x].owner = NULL;
346 /* XXX Re-arrange, unconference, etc XXX */
348 ast->tech_pvt = NULL;
351 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
352 ast_mutex_unlock(&p->lock);
353 /* Remove from list */
354 ast_mutex_lock(&featurelock);
359 prev->next = cur->next;
361 features = cur->next;
367 ast_mutex_unlock(&featurelock);
368 ast_mutex_lock(&p->lock);
371 ast_hangup(p->subchan);
372 ast_mutex_unlock(&p->lock);
373 ast_mutex_destroy(&p->lock);
377 ast_mutex_unlock(&p->lock);
381 static struct feature_pvt *features_alloc(char *data, int format)
383 struct feature_pvt *tmp;
388 struct ast_channel *chan;
390 tech = ast_strdupa(data);
392 dest = strchr(tech, '/');
398 if (!tech || !dest) {
399 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n",
403 ast_mutex_lock(&featurelock);
406 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest))
410 ast_mutex_unlock(&featurelock);
412 chan = ast_request(tech, format, dest, &status);
414 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
417 tmp = malloc(sizeof(struct feature_pvt));
419 memset(tmp, 0, sizeof(struct feature_pvt));
421 init_sub(tmp->subs + x);
422 ast_mutex_init(&tmp->lock);
423 strncpy(tmp->tech, tech, sizeof(tmp->tech) - 1);
424 strncpy(tmp->dest, dest, sizeof(tmp->dest) - 1);
426 ast_mutex_lock(&featurelock);
427 tmp->next = features;
429 ast_mutex_unlock(&featurelock);
435 static struct ast_channel *features_new(struct feature_pvt *p, int state, int index)
437 struct ast_channel *tmp;
440 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n");
443 if (p->subs[index].owner) {
444 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index);
447 tmp = ast_channel_alloc(0);
451 tmp->tech = &features_tech;
453 snprintf(tmp->name, sizeof(tmp->name), "Feature/%s/%s-%d", p->tech, p->dest, x);
457 if (p->subs[x].owner && !strcasecmp(p->subs[x].owner->name, tmp->name))
464 ast_setstate(tmp, state);
465 tmp->writeformat = p->subchan->writeformat;
466 tmp->rawwriteformat = p->subchan->rawwriteformat;
467 tmp->readformat = p->subchan->readformat;
468 tmp->rawreadformat = p->subchan->rawreadformat;
469 tmp->nativeformats = p->subchan->readformat;
471 p->subs[index].owner = tmp;
474 ast_mutex_lock(&usecnt_lock);
476 ast_mutex_unlock(&usecnt_lock);
477 ast_update_use_count();
479 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
484 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause)
486 struct feature_pvt *p;
487 struct ast_channel *chan = NULL;
488 p = features_alloc(data, format);
489 if (p && !p->subs[SUB_REAL].owner)
490 chan = features_new(p, AST_STATE_DOWN, SUB_REAL);
492 update_features(p,SUB_REAL);
496 static int features_show(int fd, int argc, char **argv)
498 struct feature_pvt *p;
501 return RESULT_SHOWUSAGE;
502 ast_mutex_lock(&featurelock);
505 ast_mutex_lock(&p->lock);
506 ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest);
507 ast_mutex_unlock(&p->lock);
511 ast_cli(fd, "No feature channels in use\n");
512 ast_mutex_unlock(&featurelock);
513 return RESULT_SUCCESS;
516 static char show_features_usage[] =
517 "Usage: feature show channels\n"
518 " Provides summary information on feature channels.\n";
520 static struct ast_cli_entry cli_show_features = {
521 { "feature", "show", "channels", NULL }, features_show,
522 "Show status of feature channels", show_features_usage, NULL };
526 /* Make sure we can register our sip channel type */
527 if (ast_channel_register(&features_tech)) {
528 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
531 ast_cli_register(&cli_show_features);
542 struct feature_pvt *p;
543 /* First, take us out of the channel loop */
544 ast_cli_unregister(&cli_show_features);
545 ast_channel_unregister(&features_tech);
546 if (!ast_mutex_lock(&featurelock)) {
547 /* Hangup all interfaces if they have an owner */
551 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
555 ast_mutex_unlock(&featurelock);
557 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
566 ast_mutex_lock(&usecnt_lock);
568 ast_mutex_unlock(&usecnt_lock);
574 return ASTERISK_GPL_KEY;
579 return (char *) desc;