18f7367cf42812b4fe298905a1c4272097fb2e76
[asterisk/asterisk.git] / channels / chan_features.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * feature Proxy Channel
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <sys/socket.h>
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <fcntl.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <sys/signal.h>
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/lock.h"
31 #include "asterisk/channel.h"
32 #include "asterisk/config.h"
33 #include "asterisk/logger.h"
34 #include "asterisk/module.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/options.h"
37 #include "asterisk/lock.h"
38 #include "asterisk/sched.h"
39 #include "asterisk/io.h"
40 #include "asterisk/rtp.h"
41 #include "asterisk/acl.h"
42 #include "asterisk/callerid.h"
43 #include "asterisk/file.h"
44 #include "asterisk/cli.h"
45 #include "asterisk/app.h"
46 #include "asterisk/musiconhold.h"
47 #include "asterisk/manager.h"
48
49 static const char desc[] = "Feature Proxy Channel";
50 static const char type[] = "Feature";
51 static const char tdesc[] = "Feature Proxy Channel Driver";
52
53 static int usecnt =0;
54 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
55
56 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
57
58 /* Protect the interface list (of feature_pvt's) */
59 AST_MUTEX_DEFINE_STATIC(featurelock);
60
61 struct feature_sub {
62         struct ast_channel *owner;
63         int inthreeway;
64         int pfd;
65         int timingfdbackup;
66         int alertpipebackup[2];
67 };
68
69 static struct feature_pvt {
70         ast_mutex_t lock;                       /* Channel private lock */
71         char tech[AST_MAX_EXTENSION];           /* Technology to abstract */
72         char dest[AST_MAX_EXTENSION];           /* Destination to abstract */
73         struct ast_channel *subchan;
74         struct feature_sub subs[3];             /* Subs */
75         struct ast_channel *owner;              /* Current Master Channel */
76         struct feature_pvt *next;               /* Next entity */
77 } *features = NULL;
78
79 #define SUB_REAL        0                       /* Active call */
80 #define SUB_CALLWAIT    1                       /* Call-Waiting call on hold */
81 #define SUB_THREEWAY    2                       /* Three-way call */
82
83 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause);
84 static int features_digit(struct ast_channel *ast, char digit);
85 static int features_call(struct ast_channel *ast, char *dest, int timeout);
86 static int features_hangup(struct ast_channel *ast);
87 static int features_answer(struct ast_channel *ast);
88 static struct ast_frame *features_read(struct ast_channel *ast);
89 static int features_write(struct ast_channel *ast, struct ast_frame *f);
90 static int features_indicate(struct ast_channel *ast, int condition);
91 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
92
93 static const struct ast_channel_tech features_tech = {
94         .type = type,
95         .description = tdesc,
96         .capabilities = -1,
97         .requester = features_request,
98         .send_digit = features_digit,
99         .call = features_call,
100         .hangup = features_hangup,
101         .answer = features_answer,
102         .read = features_read,
103         .write = features_write,
104         .exception = features_read,
105         .indicate = features_indicate,
106         .fixup = features_fixup,
107 };
108
109 static inline void init_sub(struct feature_sub *sub)
110 {
111         sub->inthreeway = 0;
112         sub->pfd = -1;
113         sub->timingfdbackup = -1;
114         sub->alertpipebackup[0] = sub->alertpipebackup[1] = -1;
115 }
116
117 static inline int indexof(struct feature_pvt *p, struct ast_channel *owner, int nullok)
118 {
119         int x;
120         if (!owner) {
121                 ast_log(LOG_WARNING, "indexof called on NULL owner??\n");
122                 return -1;
123         }
124         for (x=0;x<3;x++) {
125                 if (owner == p->subs[x].owner)
126                         return x;
127         }
128         return -1;
129 }
130
131 #if 0
132 static void wakeup_sub(struct feature_pvt *p, int a)
133 {
134         struct ast_frame null = { AST_FRAME_NULL, };
135         for (;;) {
136                 if (p->subs[a].owner) {
137                         if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
138                                 ast_mutex_unlock(&p->lock);
139                                 usleep(1);
140                                 ast_mutex_lock(&p->lock);
141                         } else {
142                                 ast_queue_frame(p->subs[a].owner, &null);
143                                 ast_mutex_unlock(&p->subs[a].owner->lock);
144                                 break;
145                         }
146                 } else
147                         break;
148         }
149 }
150 #endif
151
152 static void restore_channel(struct feature_pvt *p, int index)
153 {
154         /* Restore timing/alertpipe */
155         p->subs[index].owner->timingfd = p->subs[index].timingfdbackup;
156         p->subs[index].owner->alertpipe[0] = p->subs[index].alertpipebackup[0];
157         p->subs[index].owner->alertpipe[1] = p->subs[index].alertpipebackup[1];
158         p->subs[index].owner->fds[AST_MAX_FDS-1] = p->subs[index].alertpipebackup[0];
159         p->subs[index].owner->fds[AST_MAX_FDS-2] = p->subs[index].timingfdbackup;
160 }
161
162 static void update_features(struct feature_pvt *p, int index)
163 {
164         int x;
165         if (p->subs[index].owner) {
166                 for (x=0;x<AST_MAX_FDS;x++) {
167                         if (index) 
168                                 p->subs[index].owner->fds[x] = -1;
169                         else
170                                 p->subs[index].owner->fds[x] = p->subchan->fds[x];
171                 }
172                 if (!index) {
173                         /* Copy timings from master channel */
174                         p->subs[index].owner->timingfd = p->subchan->timingfd;
175                         p->subs[index].owner->alertpipe[0] = p->subchan->alertpipe[0];
176                         p->subs[index].owner->alertpipe[1] = p->subchan->alertpipe[1];
177                         if (p->subs[index].owner->nativeformats != p->subchan->readformat) {
178                                 p->subs[index].owner->nativeformats = p->subchan->readformat;
179                                 if (p->subs[index].owner->readformat)
180                                         ast_set_read_format(p->subs[index].owner, p->subs[index].owner->readformat);
181                                 if (p->subs[index].owner->writeformat)
182                                         ast_set_write_format(p->subs[index].owner, p->subs[index].owner->writeformat);
183                         }
184                 } else{
185                         restore_channel(p, index);
186                 }
187         }
188 }
189
190 #if 0
191 static void swap_subs(struct feature_pvt *p, int a, int b)
192 {
193         int tinthreeway;
194         struct ast_channel *towner;
195
196         ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
197
198         towner = p->subs[a].owner;
199         tinthreeway = p->subs[a].inthreeway;
200
201         p->subs[a].owner = p->subs[b].owner;
202         p->subs[a].inthreeway = p->subs[b].inthreeway;
203
204         p->subs[b].owner = towner;
205         p->subs[b].inthreeway = tinthreeway;
206         update_features(p,a);
207         update_features(p,b);
208         wakeup_sub(p, a);
209         wakeup_sub(p, b);
210 }
211 #endif
212
213 static int features_answer(struct ast_channel *ast)
214 {
215         struct feature_pvt *p = ast->tech_pvt;
216         int res = -1;
217         int x;
218         ast_mutex_lock(&p->lock);
219         x = indexof(p, ast, 0);
220         if (!x && p->subchan)
221                 res = ast_answer(p->subchan);
222         ast_mutex_unlock(&p->lock);
223         return res;
224 }
225
226 static struct ast_frame  *features_read(struct ast_channel *ast)
227 {
228         static struct ast_frame null_frame = { AST_FRAME_NULL, };
229         struct feature_pvt *p = ast->tech_pvt;
230         struct ast_frame *f;
231         int x;
232         
233         f = &null_frame;
234         ast_mutex_lock(&p->lock);
235         x = indexof(p, ast, 0);
236         if (!x && p->subchan) {
237                 update_features(p, x);
238                 f = ast_read(p->subchan);
239         }
240         ast_mutex_unlock(&p->lock);
241         return f;
242 }
243
244 static int features_write(struct ast_channel *ast, struct ast_frame *f)
245 {
246         struct feature_pvt *p = ast->tech_pvt;
247         int res = -1;
248         int x;
249         ast_mutex_lock(&p->lock);
250         x = indexof(p, ast, 0);
251         if (!x && p->subchan)
252                 res = ast_write(p->subchan, f);
253         ast_mutex_unlock(&p->lock);
254         return res;
255 }
256
257 static int features_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
258 {
259         struct feature_pvt *p = newchan->tech_pvt;
260         int x;
261         ast_mutex_lock(&p->lock);
262         if (p->owner == oldchan)
263                 p->owner = newchan;
264         for (x=0;x<3;x++) {
265                 if (p->subs[x].owner == oldchan)
266                         p->subs[x].owner = newchan;
267         }
268         ast_mutex_unlock(&p->lock);
269         return 0;
270 }
271
272 static int features_indicate(struct ast_channel *ast, int condition)
273 {
274         struct feature_pvt *p = ast->tech_pvt;
275         int res = -1;
276         int x;
277         /* Queue up a frame representing the indication as a control frame */
278         ast_mutex_lock(&p->lock);
279         x = indexof(p, ast, 0);
280         if (!x && p->subchan)
281                 res = ast_indicate(p->subchan, condition);
282         ast_mutex_unlock(&p->lock);
283         return res;
284 }
285
286 static int features_digit(struct ast_channel *ast, char digit)
287 {
288         struct feature_pvt *p = ast->tech_pvt;
289         int res = -1;
290         int x;
291         /* Queue up a frame representing the indication as a control frame */
292         ast_mutex_lock(&p->lock);
293         x = indexof(p, ast, 0);
294         if (!x && p->subchan)
295                 res = ast_senddigit(p->subchan, digit);
296         ast_mutex_unlock(&p->lock);
297         return res;
298 }
299
300 static int features_call(struct ast_channel *ast, char *dest, int timeout)
301 {
302         struct feature_pvt *p = ast->tech_pvt;
303         int res = -1;
304         int x;
305         char *dest2;
306                 
307         dest2 = strchr(dest, '/');
308         if (dest2) {
309                 ast_mutex_lock(&p->lock);
310                 x = indexof(p, ast, 0);
311                 if (!x && p->subchan) {
312                         if (p->owner->cid.cid_num)
313                                 p->subchan->cid.cid_num = strdup(p->owner->cid.cid_num);
314                         else 
315                                 p->subchan->cid.cid_num = NULL;
316                 
317                         if (p->owner->cid.cid_name)
318                                 p->subchan->cid.cid_name = strdup(p->owner->cid.cid_name);
319                         else 
320                                 p->subchan->cid.cid_name = NULL;
321                 
322                         if (p->owner->cid.cid_rdnis)
323                                 p->subchan->cid.cid_rdnis = strdup(p->owner->cid.cid_rdnis);
324                         else
325                                 p->subchan->cid.cid_rdnis = NULL;
326                 
327                         if (p->owner->cid.cid_ani)
328                                 p->subchan->cid.cid_ani = strdup(p->owner->cid.cid_ani);
329                         else
330                                 p->subchan->cid.cid_ani = NULL;
331                 
332                         strncpy(p->subchan->language, p->owner->language, sizeof(p->subchan->language) - 1);
333                         strncpy(p->subchan->accountcode, p->owner->accountcode, sizeof(p->subchan->accountcode) - 1);
334                         p->subchan->cdrflags = p->owner->cdrflags;
335                         res = ast_call(p->subchan, dest2, timeout);
336                         update_features(p, x);
337                 } else
338                         ast_log(LOG_NOTICE, "Uhm yah, not quite there with the call waiting...\n");
339                 ast_mutex_unlock(&p->lock);
340         }
341         return res;
342 }
343
344 static int features_hangup(struct ast_channel *ast)
345 {
346         struct feature_pvt *p = ast->tech_pvt;
347         struct feature_pvt *cur, *prev=NULL;
348         int x;
349
350         ast_mutex_lock(&p->lock);
351         x = indexof(p, ast, 0);
352         if (x > -1) {
353                 restore_channel(p, x);
354                 p->subs[x].owner = NULL;
355                 /* XXX Re-arrange, unconference, etc XXX */
356         }
357         ast->tech_pvt = NULL;
358         
359         
360         if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
361                 ast_mutex_unlock(&p->lock);
362                 /* Remove from list */
363                 ast_mutex_lock(&featurelock);
364                 cur = features;
365                 while(cur) {
366                         if (cur == p) {
367                                 if (prev)
368                                         prev->next = cur->next;
369                                 else
370                                         features = cur->next;
371                                 break;
372                         }
373                         prev = cur;
374                         cur = cur->next;
375                 }
376                 ast_mutex_unlock(&featurelock);
377                 ast_mutex_lock(&p->lock);
378                 /* And destroy */
379                 if (p->subchan)
380                         ast_hangup(p->subchan);
381                 ast_mutex_unlock(&p->lock);
382                 ast_mutex_destroy(&p->lock);
383                 free(p);
384                 return 0;
385         }
386         ast_mutex_unlock(&p->lock);
387         return 0;
388 }
389
390 static struct feature_pvt *features_alloc(char *data, int format)
391 {
392         struct feature_pvt *tmp;
393         char *dest=NULL;
394         char *tech;
395         int x;
396         int status;
397         struct ast_channel *chan;
398         
399         tech = ast_strdupa(data);
400         if (tech) {
401                 dest = strchr(tech, '/');
402                 if (dest) {
403                         *dest = '\0';
404                         dest++;
405                 }
406         }
407         if (!tech || !dest) {
408                 ast_log(LOG_NOTICE, "Format for feature channel is Feature/Tech/Dest ('%s' not valid)!\n", 
409                         data);
410                 return NULL;
411         }
412         ast_mutex_lock(&featurelock);
413         tmp = features;
414         while(tmp) {
415                 if (!strcasecmp(tmp->tech, tech) && !strcmp(tmp->dest, dest))
416                         break;
417                 tmp = tmp->next;
418         }
419         ast_mutex_unlock(&featurelock);
420         if (!tmp) {
421                 chan = ast_request(tech, format, dest, &status);
422                 if (!chan) {
423                         ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
424                         return NULL;
425                 }
426                 tmp = malloc(sizeof(struct feature_pvt));
427                 if (tmp) {
428                         memset(tmp, 0, sizeof(struct feature_pvt));
429                         for (x=0;x<3;x++)
430                                 init_sub(tmp->subs + x);
431                         ast_mutex_init(&tmp->lock);
432                         strncpy(tmp->tech, tech, sizeof(tmp->tech) - 1);
433                         strncpy(tmp->dest, dest, sizeof(tmp->dest) - 1);
434                         tmp->subchan = chan;
435                         ast_mutex_lock(&featurelock);
436                         tmp->next = features;
437                         features = tmp;
438                         ast_mutex_unlock(&featurelock);
439                 }
440         }
441         return tmp;
442 }
443
444 static struct ast_channel *features_new(struct feature_pvt *p, int state, int index)
445 {
446         struct ast_channel *tmp;
447         int x,y;
448         if (!p->subchan) {
449                 ast_log(LOG_WARNING, "Called upon channel with no subchan:(\n");
450                 return NULL;
451         }
452         if (p->subs[index].owner) {
453                 ast_log(LOG_WARNING, "Called to put index %d already there!\n", index);
454                 return NULL;
455         }
456         tmp = ast_channel_alloc(0);
457         if (!tmp) {
458                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
459                 return NULL;
460         }
461         tmp->tech = &features_tech;
462         for (x=1;x<4;x++) {
463                 snprintf(tmp->name, sizeof(tmp->name), "Feature/%s/%s-%d", p->tech, p->dest, x);
464                 for (y=0;y<3;y++) {
465                         if (y == index)
466                                 continue;
467                         if (p->subs[y].owner && !strcasecmp(p->subs[y].owner->name, tmp->name))
468                                 break;
469                 }
470                 if (y >= 3)
471                         break;
472         }
473         tmp->type = type;
474         ast_setstate(tmp, state);
475         tmp->writeformat = p->subchan->writeformat;
476         tmp->rawwriteformat = p->subchan->rawwriteformat;
477         tmp->readformat = p->subchan->readformat;
478         tmp->rawreadformat = p->subchan->rawreadformat;
479         tmp->nativeformats = p->subchan->readformat;
480         tmp->tech_pvt = p;
481         p->subs[index].owner = tmp;
482         if (!p->owner)
483                 p->owner = tmp;
484         ast_mutex_lock(&usecnt_lock);
485         usecnt++;
486         ast_mutex_unlock(&usecnt_lock);
487         ast_update_use_count();
488         return tmp;
489 }
490
491
492 static struct ast_channel *features_request(const char *type, int format, void *data, int *cause)
493 {
494         struct feature_pvt *p;
495         struct ast_channel *chan = NULL;
496         p = features_alloc(data, format);
497         if (p && !p->subs[SUB_REAL].owner)
498                 chan = features_new(p, AST_STATE_DOWN, SUB_REAL);
499         if (chan)
500                 update_features(p,SUB_REAL);
501         return chan;
502 }
503
504 static int features_show(int fd, int argc, char **argv)
505 {
506         struct feature_pvt *p;
507
508         if (argc != 3)
509                 return RESULT_SHOWUSAGE;
510         ast_mutex_lock(&featurelock);
511         p = features;
512         while(p) {
513                 ast_mutex_lock(&p->lock);
514                 ast_cli(fd, "%s -- %s/%s\n", p->owner ? p->owner->name : "<unowned>", p->tech, p->dest);
515                 ast_mutex_unlock(&p->lock);
516                 p = p->next;
517         }
518         if (!features)
519                 ast_cli(fd, "No feature channels in use\n");
520         ast_mutex_unlock(&featurelock);
521         return RESULT_SUCCESS;
522 }
523
524 static char show_features_usage[] = 
525 "Usage: feature show channels\n"
526 "       Provides summary information on feature channels.\n";
527
528 static struct ast_cli_entry cli_show_features = {
529         { "feature", "show", "channels", NULL }, features_show, 
530         "Show status of feature channels", show_features_usage, NULL };
531
532 int load_module()
533 {
534         /* Make sure we can register our sip channel type */
535         if (ast_channel_register(&features_tech)) {
536                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
537                 return -1;
538         }
539         ast_cli_register(&cli_show_features);
540         return 0;
541 }
542
543 int reload()
544 {
545         return 0;
546 }
547
548 int unload_module()
549 {
550         struct feature_pvt *p;
551         /* First, take us out of the channel loop */
552         ast_cli_unregister(&cli_show_features);
553         ast_channel_unregister(&features_tech);
554         if (!ast_mutex_lock(&featurelock)) {
555                 /* Hangup all interfaces if they have an owner */
556                 p = features;
557                 while(p) {
558                         if (p->owner)
559                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
560                         p = p->next;
561                 }
562                 features = NULL;
563                 ast_mutex_unlock(&featurelock);
564         } else {
565                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
566                 return -1;
567         }               
568         return 0;
569 }
570
571 int usecount()
572 {
573         int res;
574         ast_mutex_lock(&usecnt_lock);
575         res = usecnt;
576         ast_mutex_unlock(&usecnt_lock);
577         return res;
578 }
579
580 char *key()
581 {
582         return ASTERISK_GPL_KEY;
583 }
584
585 char *description()
586 {
587         return (char *) desc;
588 }
589