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