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