2 * Asterisk -- A telephony toolkit for Linux.
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
22 #include <asterisk/sched.h>
23 #include <asterisk/options.h>
24 #include <asterisk/channel.h>
25 #include <asterisk/channel_pvt.h>
26 #include <asterisk/logger.h>
27 #include <asterisk/file.h>
28 #include <asterisk/translate.h>
33 /* Convenient mutex debugging functions */
34 #define PTHREAD_MUTEX_LOCK(a) __PTHREAD_MUTEX_LOCK(__FUNCTION__, a)
35 #define PTHREAD_MUTEX_UNLOCK(a) __PTHREAD_MUTEX_UNLOCK(__FUNCTION__, a)
37 static int __PTHREAD_MUTEX_LOCK(char *f, pthread_mutex_t *a) {
38 ast_log(LOG_DEBUG, "Locking %p (%s)\n", a, f);
39 return pthread_mutex_lock(a);
42 static int __PTHREAD_MUTEX_UNLOCK(char *f, pthread_mutex_t *a) {
43 ast_log(LOG_DEBUG, "Unlocking %p (%s)\n", a, f);
44 return pthread_mutex_unlock(a);
47 #define PTHREAD_MUTEX_LOCK(a) pthread_mutex_lock(a)
48 #define PTHREAD_MUTEX_UNLOCK(a) pthread_mutex_unlock(a)
55 struct ast_channel * (*requester)(char *type, int format, void *data);
56 struct chanlist *next;
58 struct ast_channel *channels = NULL;
60 /* Protect the channel list (highly unlikely that two things would change
61 it at the same time, but still! */
63 static pthread_mutex_t chlock = PTHREAD_MUTEX_INITIALIZER;
65 int ast_channel_register(char *type, char *description, int capabilities,
66 struct ast_channel *(*requester)(char *type, int format, void *data))
68 struct chanlist *chan, *last=NULL;
69 if (PTHREAD_MUTEX_LOCK(&chlock)) {
70 ast_log(LOG_WARNING, "Unable to lock channel list\n");
75 if (!strcasecmp(type, chan->type)) {
76 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
77 PTHREAD_MUTEX_UNLOCK(&chlock);
83 chan = malloc(sizeof(struct chanlist));
85 ast_log(LOG_WARNING, "Out of memory\n");
86 PTHREAD_MUTEX_UNLOCK(&chlock);
89 strncpy(chan->type, type, sizeof(chan->type));
90 strncpy(chan->description, description, sizeof(chan->description));
91 chan->capabilities = capabilities;
92 chan->requester = requester;
99 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
100 else if (option_verbose > 1)
101 ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
102 PTHREAD_MUTEX_UNLOCK(&chlock);
106 struct ast_channel *ast_channel_alloc(void)
108 struct ast_channel *tmp;
109 struct ast_channel_pvt *pvt;
110 PTHREAD_MUTEX_LOCK(&chlock);
111 tmp = malloc(sizeof(struct ast_channel));
112 memset(tmp, 0, sizeof(struct ast_channel));
114 pvt = malloc(sizeof(struct ast_channel_pvt));
116 memset(pvt, 0, sizeof(struct ast_channel_pvt));
117 tmp->sched = sched_context_create();
120 strncpy(tmp->name, "**Unknown**", sizeof(tmp->name));
122 tmp->state = AST_STATE_DOWN;
127 pthread_mutex_init(&tmp->lock, NULL);
128 strncpy(tmp->context, "default", sizeof(tmp->context));
129 strncpy(tmp->language, defaultlanguage, sizeof(tmp->language));
130 strncpy(tmp->exten, "s", sizeof(tmp->exten));
132 tmp->next = channels;
135 ast_log(LOG_WARNING, "Unable to create schedule context\n");
140 ast_log(LOG_WARNING, "Out of memory\n");
145 ast_log(LOG_WARNING, "Out of memory\n");
146 PTHREAD_MUTEX_UNLOCK(&chlock);
150 struct ast_channel *ast_channel_walk(struct ast_channel *prev)
152 struct ast_channel *l, *ret=NULL;
153 PTHREAD_MUTEX_LOCK(&chlock);
156 PTHREAD_MUTEX_UNLOCK(&chlock);
164 PTHREAD_MUTEX_UNLOCK(&chlock);
169 void ast_channel_free(struct ast_channel *chan)
171 struct ast_channel *last=NULL, *cur;
172 PTHREAD_MUTEX_LOCK(&chlock);
177 last->next = cur->next;
179 channels = cur->next;
186 ast_log(LOG_WARNING, "Unable to find channel in list\n");
188 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
189 /* Free translatosr */
190 if (chan->pvt->readtrans)
191 ast_translator_free_path(chan->pvt->readtrans);
192 if (chan->pvt->writetrans)
193 ast_translator_free_path(chan->pvt->writetrans);
195 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
199 free(chan->callerid);
200 pthread_mutex_destroy(&chan->lock);
203 PTHREAD_MUTEX_UNLOCK(&chlock);
206 int ast_softhangup(struct ast_channel *chan)
210 ast_stopstream(chan);
212 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
213 if (chan->pvt->hangup)
214 res = chan->pvt->hangup(chan);
216 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
218 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
219 /* Interrupt any select call or such */
221 pthread_kill(chan->blocker, SIGURG);
225 int ast_hangup(struct ast_channel *chan)
229 ast_stopstream(chan);
231 sched_context_destroy(chan->sched);
232 if (chan->blocking) {
233 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
234 "is blocked by thread %ld in procedure %s! Expect a failure\n",
235 pthread_self(), chan->name, chan->blocker, chan->blockproc);
239 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
240 if (chan->pvt->hangup)
241 res = chan->pvt->hangup(chan);
242 ast_channel_free(chan);
246 void ast_channel_unregister(char *type)
248 struct chanlist *chan, *last=NULL;
250 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
251 if (PTHREAD_MUTEX_LOCK(&chlock)) {
252 ast_log(LOG_WARNING, "Unable to lock channel list\n");
257 if (!strcasecmp(chan->type, type)) {
259 last->next = chan->next;
261 backends = backends->next;
263 PTHREAD_MUTEX_UNLOCK(&chlock);
269 PTHREAD_MUTEX_UNLOCK(&chlock);
272 int ast_answer(struct ast_channel *chan)
274 /* Answer the line, if possible */
275 if (chan->state == AST_STATE_RING) {
276 if (chan->pvt->answer)
277 return chan->pvt->answer(chan);
282 int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
284 /* Wait for x amount of time on a file descriptor to have input. */
291 tv.tv_sec = *ms / 1000;
292 tv.tv_usec = (*ms % 1000) * 1000;
296 FD_SET(fds[x], &rfds);
297 FD_SET(fds[x], &efds);
302 res = select(max + 1, &rfds, NULL, &efds, &tv);
304 res = select(max + 1, &rfds, NULL, &efds, NULL);
306 if ((FD_ISSET(fds[x], &rfds) || FD_ISSET(fds[x], &efds)) && (winner < 0)) {
308 *exception = FD_ISSET(fds[x], &efds);
312 *ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
318 struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
320 /* Wait for x amount of time on a file descriptor to have input. */
325 struct ast_channel *winner = NULL;
327 tv.tv_sec = *ms / 1000;
328 tv.tv_usec = (*ms % 1000) * 1000;
332 FD_SET(c[x]->fd, &rfds);
333 FD_SET(c[x]->fd, &efds);
334 CHECK_BLOCKING(c[x]);
339 res = select(max + 1, &rfds, NULL, &efds, &tv);
341 res = select(max + 1, &rfds, NULL, &efds, NULL);
344 if ((FD_ISSET(c[x]->fd, &rfds) || FD_ISSET(c[x]->fd, &efds)) && !winner) {
345 /* Set exception flag if appropriate */
346 if (FD_ISSET(c[x]->fd, &efds))
351 *ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
357 int ast_waitfor(struct ast_channel *c, int ms)
359 if (ast_waitfor_n(&c, 1, &ms)) {
364 /* Error if ms < 0 */
370 char ast_waitfordigit(struct ast_channel *c, int ms)
374 /* Wait for a digit, no more than ms milliseconds total. */
375 while(ms && !result) {
376 ms = ast_waitfor(c, ms);
377 if (ms < 0) /* Error */
383 if (f->frametype == AST_FRAME_DTMF)
384 result = f->subclass;
393 struct ast_frame *ast_read(struct ast_channel *chan)
395 struct ast_frame *f = NULL;
396 static struct ast_frame null_frame =
400 chan->blocker = pthread_self();
401 if (chan->exception) {
402 if (chan->pvt->exception)
403 f = chan->pvt->exception(chan);
405 ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n");
406 /* Clear the exception flag */
410 f = chan->pvt->read(chan);
412 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan);
413 if (f && (f->frametype == AST_FRAME_VOICE)) {
414 if (chan->pvt->readtrans) {
415 f = ast_translate(chan->pvt->readtrans, f, 1);
423 int ast_sendtext(struct ast_channel *chan, char *text)
426 CHECK_BLOCKING(chan);
427 if (chan->pvt->send_text)
428 res = chan->pvt->send_text(chan, text);
433 int ast_write(struct ast_channel *chan, struct ast_frame *fr)
437 CHECK_BLOCKING(chan);
438 switch(fr->frametype) {
439 case AST_FRAME_CONTROL:
440 /* XXX Interpret control frames XXX */
441 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
445 if (chan->pvt->send_digit)
446 res = chan->pvt->send_digit(chan, fr->subclass);
449 if (chan->pvt->write) {
450 if (chan->pvt->writetrans) {
451 f = ast_translate(chan->pvt->writetrans, fr, 1);
455 res = chan->pvt->write(chan, f);
462 int ast_set_write_format(struct ast_channel *chan, int fmts)
468 native = chan->nativeformats;
471 res = ast_translator_best_choice(&native, &fmt);
473 ast_log(LOG_NOTICE, "Unable to find a path from %d to %d\n", fmts, chan->nativeformats);
477 /* Now we have a good choice for both. We'll write using our native format. */
478 chan->pvt->rawwriteformat = native;
479 /* User perspective is fmt */
480 chan->writeformat = fmt;
481 /* Free any write translation we have right now */
482 if (chan->pvt->writetrans)
483 ast_translator_free_path(chan->pvt->writetrans);
484 /* Build a translation path from the user write format to the raw writing format */
485 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
486 ast_log(LOG_DEBUG, "Set channel %s to format %d\n", chan->name, chan->writeformat);
490 int ast_set_read_format(struct ast_channel *chan, int fmts)
496 native = chan->nativeformats;
498 /* Find a translation path from the native read format to one of the user's read formats */
499 res = ast_translator_best_choice(&fmt, &native);
501 ast_log(LOG_NOTICE, "Unable to find a path from %d to %d\n", chan->nativeformats, fmts);
505 /* Now we have a good choice for both. We'll write using our native format. */
506 chan->pvt->rawreadformat = native;
507 /* User perspective is fmt */
508 chan->readformat = fmt;
509 /* Free any read translation we have right now */
510 if (chan->pvt->readtrans)
511 ast_translator_free_path(chan->pvt->readtrans);
512 /* Build a translation path from the raw read format to the user reading format */
513 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
517 struct ast_channel *ast_request(char *type, int format, void *data)
519 struct chanlist *chan;
520 struct ast_channel *c = NULL;
524 if (PTHREAD_MUTEX_LOCK(&chlock)) {
525 ast_log(LOG_WARNING, "Unable to lock channel list\n");
530 if (!strcasecmp(type, chan->type)) {
531 capabilities = chan->capabilities;
533 res = ast_translator_best_choice(&fmt, &capabilities);
535 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
536 PTHREAD_MUTEX_UNLOCK(&chlock);
539 PTHREAD_MUTEX_UNLOCK(&chlock);
541 c = chan->requester(type, capabilities, data);
547 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
548 PTHREAD_MUTEX_UNLOCK(&chlock);
552 int ast_call(struct ast_channel *chan, char *addr, int timeout)
554 /* Place an outgoing call, but don't wait any longer than timeout ms before returning.
555 If the remote end does not answer within the timeout, then do NOT hang up, but
559 res = chan->pvt->call(chan, addr, timeout);
563 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
571 if (c->streamid > -1) {
572 d = ast_waitstream(c, AST_DIGIT_ANY);
576 d = ast_waitfordigit(c, to);
578 d = ast_waitfordigit(c, to);
582 if (!strchr(enders, d))
584 if ((d == 0) || strchr(enders, d) || (pos >= len - 1)) {
594 int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
599 peerf = peer->nativeformats;
600 chanf = chan->nativeformats;
601 res = ast_translator_best_choice(&peerf, &chanf);
603 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan, chan->nativeformats, peer, peer->nativeformats);
606 /* Set read format on channel */
607 res = ast_set_read_format(chan, peerf);
609 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan, chanf);
612 /* Set write format on peer channel */
613 res = ast_set_write_format(peer, peerf);
615 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer, peerf);
618 /* Now we go the other way */
619 peerf = peer->nativeformats;
620 chanf = chan->nativeformats;
621 res = ast_translator_best_choice(&chanf, &peerf);
623 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer, peer->nativeformats, chan, chan->nativeformats);
626 /* Set writeformat on channel */
627 res = ast_set_write_format(chan, chanf);
629 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan, chanf);
632 /* Set read format on peer channel */
633 res = ast_set_read_format(peer, chanf);
635 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer, peerf);
643 int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
645 /* Copy voice back and forth between the two channels. Give the peer
646 the ability to transfer calls with '#<extension' syntax. */
647 struct ast_channel *cs[3];
650 struct ast_channel *who;
651 if (c0->pvt->bridge &&
652 (c0->pvt->bridge == c1->pvt->bridge)) {
653 /* Looks like they share a bridge code */
654 if (!c0->pvt->bridge(c0, c1, flags, fo, rc))
656 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
657 /* If they return non-zero then continue on normally */
665 who = ast_waitfor_n(cs, 2, &to);
667 ast_log(LOG_WARNING, "Nobody there??\n");
676 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
681 if ((f->frametype == AST_FRAME_VOICE) ||
682 (f->frametype == AST_FRAME_TEXT) ||
683 (f->frametype == AST_FRAME_VIDEO) ||
684 (f->frametype == AST_FRAME_IMAGE) ||
685 (f->frametype == AST_FRAME_DTMF)) {
686 if ((f->frametype == AST_FRAME_DTMF) && (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
687 if ((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
690 /* Take out of conference mode */
693 if ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
700 ast_log(LOG_DEBUG, "Read from %s\n", who->name);
702 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
713 /* Swap who gets priority */