00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <sys/time.h>
00018 #include <signal.h>
00019 #include <errno.h>
00020 #include <unistd.h>
00021 #include <math.h>
00022 #include <sys/poll.h>
00023 #include <asterisk/pbx.h>
00024 #include <asterisk/frame.h>
00025 #include <asterisk/sched.h>
00026 #include <asterisk/options.h>
00027 #include <asterisk/channel.h>
00028 #include <asterisk/channel_pvt.h>
00029 #include <asterisk/logger.h>
00030 #include <asterisk/say.h>
00031 #include <asterisk/file.h>
00032 #include <asterisk/translate.h>
00033 #include <asterisk/manager.h>
00034 #include <asterisk/chanvars.h>
00035 #include <asterisk/linkedlists.h>
00036 #include <asterisk/indications.h>
00037 #include <asterisk/monitor.h>
00038 #include <asterisk/causes.h>
00039 #include <asterisk/utils.h>
00040 #include <asterisk/lock.h>
00041 #ifdef ZAPTEL_OPTIMIZATIONS
00042 #include <sys/ioctl.h>
00043 #ifdef __linux__
00044 #include "/usr/src/modules/zaptel/zaptel.h"
00045 #else
00046 #include <zaptel.h>
00047 #endif
00048 #ifndef ZT_TIMERPING
00049 #error "You need newer zaptel! Please cvs update zaptel"
00050 #endif
00051 #endif
00052
00053
00054 #if 0
00055 #define MONITOR_CONSTANT_DELAY
00056 #define MONITOR_DELAY 150 * 8
00057 #endif
00058
00059 static int shutting_down = 0;
00060 static int uniqueint = 0;
00061
00062
00063
00064 struct chanlist {
00065 char type[80];
00066 char description[80];
00067 int capabilities;
00068 struct ast_channel * (*requester)(char *type, int format, void *data);
00069 int (*devicestate)(void *data);
00070 struct chanlist *next;
00071 } *backends = NULL;
00072 struct ast_channel *channels = NULL;
00073
00074
00075
00076
00077 AST_MUTEX_DEFINE_STATIC(chlock);
00078
00079 int ast_check_hangup(struct ast_channel *chan)
00080 {
00081 time_t myt;
00082
00083
00084 if (chan->_softhangup) return 1;
00085
00086 if (!chan->pvt->pvt) return 1;
00087
00088 if (!chan->whentohangup) return 0;
00089 time(&myt);
00090
00091 if (chan->whentohangup > myt) return 0;
00092 chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
00093 return 1;
00094 }
00095
00096 static int ast_check_hangup_locked(struct ast_channel *chan)
00097 {
00098 int res;
00099 ast_mutex_lock(&chan->lock);
00100 res = ast_check_hangup(chan);
00101 ast_mutex_unlock(&chan->lock);
00102 return res;
00103 }
00104
00105 void ast_begin_shutdown(int hangup)
00106 {
00107 struct ast_channel *c;
00108 shutting_down = 1;
00109 if (hangup) {
00110 ast_mutex_lock(&chlock);
00111 c = channels;
00112 while(c) {
00113 ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
00114 c = c->next;
00115 }
00116 ast_mutex_unlock(&chlock);
00117 }
00118 }
00119
00120 int ast_active_channels(void)
00121 {
00122 struct ast_channel *c;
00123 int cnt = 0;
00124 ast_mutex_lock(&chlock);
00125 c = channels;
00126 while(c) {
00127 cnt++;
00128 c = c->next;
00129 }
00130 ast_mutex_unlock(&chlock);
00131 return cnt;
00132 }
00133
00134 void ast_cancel_shutdown(void)
00135 {
00136 shutting_down = 0;
00137 }
00138
00139 int ast_shutting_down(void)
00140 {
00141 return shutting_down;
00142 }
00143
00144 void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
00145 {
00146 time_t myt;
00147
00148 time(&myt);
00149 if (offset)
00150 chan->whentohangup = myt + offset;
00151 else
00152 chan->whentohangup = 0;
00153 return;
00154 }
00155
00156 int ast_channel_register(char *type, char *description, int capabilities,
00157 struct ast_channel *(*requester)(char *type, int format, void *data))
00158 {
00159 return ast_channel_register_ex(type, description, capabilities, requester, NULL);
00160 }
00161
00162 int ast_channel_register_ex(char *type, char *description, int capabilities,
00163 struct ast_channel *(*requester)(char *type, int format, void *data),
00164 int (*devicestate)(void *data))
00165 {
00166 struct chanlist *chan, *last=NULL;
00167 if (ast_mutex_lock(&chlock)) {
00168 ast_log(LOG_WARNING, "Unable to lock channel list\n");
00169 return -1;
00170 }
00171 chan = backends;
00172 while (chan) {
00173 if (!strcasecmp(type, chan->type)) {
00174 ast_log(LOG_WARNING, "Already have a handler for type '%s'\n", type);
00175 ast_mutex_unlock(&chlock);
00176 return -1;
00177 }
00178 last = chan;
00179 chan = chan->next;
00180 }
00181 chan = malloc(sizeof(struct chanlist));
00182 if (!chan) {
00183 ast_log(LOG_WARNING, "Out of memory\n");
00184 ast_mutex_unlock(&chlock);
00185 return -1;
00186 }
00187 strncpy(chan->type, type, sizeof(chan->type)-1);
00188 strncpy(chan->description, description, sizeof(chan->description)-1);
00189 chan->capabilities = capabilities;
00190 chan->requester = requester;
00191 chan->devicestate = devicestate;
00192 chan->next = NULL;
00193 if (last)
00194 last->next = chan;
00195 else
00196 backends = chan;
00197 if (option_debug)
00198 ast_log(LOG_DEBUG, "Registered handler for '%s' (%s)\n", chan->type, chan->description);
00199 else if (option_verbose > 1)
00200 ast_verbose( VERBOSE_PREFIX_2 "Registered channel type '%s' (%s)\n", chan->type, chan->description);
00201 ast_mutex_unlock(&chlock);
00202 return 0;
00203 }
00204
00205 char *ast_state2str(int state)
00206 {
00207
00208 static char localtmp[256];
00209 switch(state) {
00210 case AST_STATE_DOWN:
00211 return "Down";
00212 case AST_STATE_RESERVED:
00213 return "Rsrvd";
00214 case AST_STATE_OFFHOOK:
00215 return "OffHook";
00216 case AST_STATE_DIALING:
00217 return "Dialing";
00218 case AST_STATE_RING:
00219 return "Ring";
00220 case AST_STATE_RINGING:
00221 return "Ringing";
00222 case AST_STATE_UP:
00223 return "Up";
00224 case AST_STATE_BUSY:
00225 return "Busy";
00226 default:
00227 snprintf(localtmp, sizeof(localtmp), "Unknown (%d)\n", state);
00228 return localtmp;
00229 }
00230 }
00231
00232
00233 int ast_best_codec(int fmts)
00234 {
00235
00236
00237 int x;
00238 static int prefs[] =
00239 {
00240
00241 AST_FORMAT_ULAW,
00242
00243 AST_FORMAT_ALAW,
00244
00245 AST_FORMAT_SLINEAR,
00246
00247 AST_FORMAT_G726,
00248
00249 AST_FORMAT_ADPCM,
00250
00251
00252 AST_FORMAT_GSM,
00253
00254 AST_FORMAT_ILBC,
00255
00256 AST_FORMAT_SPEEX,
00257
00258
00259 AST_FORMAT_LPC10,
00260
00261 AST_FORMAT_G729A,
00262
00263 AST_FORMAT_G723_1,
00264 };
00265
00266
00267 for (x=0;x<sizeof(prefs) / sizeof(prefs[0]); x++)
00268 if (fmts & prefs[x])
00269 return prefs[x];
00270 ast_log(LOG_WARNING, "Don't know any of 0x%x formats\n", fmts);
00271 return 0;
00272 }
00273
00274 struct ast_channel *ast_channel_alloc(int needqueue)
00275 {
00276 struct ast_channel *tmp;
00277 struct ast_channel_pvt *pvt;
00278 int x;
00279 int flags;
00280 struct varshead *headp;
00281
00282
00283
00284 if (shutting_down)
00285 return NULL;
00286 ast_mutex_lock(&chlock);
00287 tmp = malloc(sizeof(struct ast_channel));
00288 if (tmp) {
00289 memset(tmp, 0, sizeof(struct ast_channel));
00290 pvt = malloc(sizeof(struct ast_channel_pvt));
00291 if (pvt) {
00292 memset(pvt, 0, sizeof(struct ast_channel_pvt));
00293 tmp->sched = sched_context_create();
00294 if (tmp->sched) {
00295 for (x=0;x<AST_MAX_FDS - 1;x++)
00296 tmp->fds[x] = -1;
00297 #ifdef ZAPTEL_OPTIMIZATIONS
00298 tmp->timingfd = open("/dev/zap/timer", O_RDWR);
00299 if (tmp->timingfd > -1) {
00300
00301
00302 flags = 1;
00303 if (!ioctl(tmp->timingfd, ZT_TIMERPONG, &flags))
00304 needqueue = 0;
00305 }
00306 #else
00307 tmp->timingfd = -1;
00308 #endif
00309 if (needqueue &&
00310 pipe(pvt->alertpipe)) {
00311 ast_log(LOG_WARNING, "Alert pipe creation failed!\n");
00312 free(pvt);
00313 free(tmp);
00314 tmp = NULL;
00315 pvt = NULL;
00316 } else {
00317 if (needqueue) {
00318 flags = fcntl(pvt->alertpipe[0], F_GETFL);
00319 fcntl(pvt->alertpipe[0], F_SETFL, flags | O_NONBLOCK);
00320 flags = fcntl(pvt->alertpipe[1], F_GETFL);
00321 fcntl(pvt->alertpipe[1], F_SETFL, flags | O_NONBLOCK);
00322 } else
00323
00324 pvt->alertpipe[0] = pvt->alertpipe[1] = -1;
00325
00326 tmp->fds[AST_MAX_FDS-1] = pvt->alertpipe[0];
00327
00328 tmp->fds[AST_MAX_FDS-2] = tmp->timingfd;
00329 strncpy(tmp->name, "**Unknown**", sizeof(tmp->name)-1);
00330 tmp->pvt = pvt;
00331
00332 tmp->_state = AST_STATE_DOWN;
00333 tmp->stack = -1;
00334 tmp->streamid = -1;
00335 tmp->appl = NULL;
00336 tmp->data = NULL;
00337 tmp->fin = 0;
00338 tmp->fout = 0;
00339 snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long)time(NULL), uniqueint++);
00340 headp=&tmp->varshead;
00341 ast_mutex_init(&tmp->lock);
00342 AST_LIST_HEAD_INIT(headp);
00343 tmp->vars=ast_var_assign("tempvar","tempval");
00344 AST_LIST_INSERT_HEAD(headp,tmp->vars,entries);
00345 strncpy(tmp->context, "default", sizeof(tmp->context)-1);
00346 strncpy(tmp->language, defaultlanguage, sizeof(tmp->language)-1);
00347 strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
00348 tmp->priority=1;
00349 tmp->amaflags = ast_default_amaflags;
00350 strncpy(tmp->accountcode, ast_default_accountcode, sizeof(tmp->accountcode)-1);
00351 tmp->next = channels;
00352 channels= tmp;
00353 }
00354 } else {
00355 ast_log(LOG_WARNING, "Unable to create schedule context\n");
00356 free(tmp);
00357 tmp = NULL;
00358 }
00359 } else {
00360 ast_log(LOG_WARNING, "Out of memory\n");
00361 free(tmp);
00362 tmp = NULL;
00363 }
00364 } else
00365 ast_log(LOG_WARNING, "Out of memory\n");
00366 ast_mutex_unlock(&chlock);
00367 return tmp;
00368 }
00369
00370 int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
00371 {
00372 struct ast_frame *f;
00373 struct ast_frame *prev, *cur;
00374 int blah = 1;
00375 int qlen = 0;
00376
00377 f = ast_frdup(fin);
00378 if (!f) {
00379 ast_log(LOG_WARNING, "Unable to duplicate frame\n");
00380 return -1;
00381 }
00382 ast_mutex_lock(&chan->lock);
00383 prev = NULL;
00384 cur = chan->pvt->readq;
00385 while(cur) {
00386 if ((cur->frametype == AST_FRAME_CONTROL) && (cur->subclass == AST_CONTROL_HANGUP)) {
00387
00388 ast_frfree(f);
00389 ast_mutex_unlock(&chan->lock);
00390 return 0;
00391 }
00392 prev = cur;
00393 cur = cur->next;
00394 qlen++;
00395 }
00396
00397 if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) {
00398 if (fin->frametype != AST_FRAME_VOICE) {
00399 ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
00400 CRASH;
00401 } else {
00402 ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
00403 ast_frfree(f);
00404 ast_mutex_unlock(&chan->lock);
00405 return 0;
00406 }
00407 }
00408 if (prev)
00409 prev->next = f;
00410 else
00411 chan->pvt->readq = f;
00412 if (chan->pvt->alertpipe[1] > -1) {
00413 if (write(chan->pvt->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
00414 ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
00415 chan->name, f->frametype, f->subclass, qlen, strerror(errno));
00416 #ifdef ZAPTEL_OPTIMIZATIONS
00417 } else if (chan->timingfd > -1) {
00418 ioctl(chan->timingfd, ZT_TIMERPING, &blah);
00419 #endif
00420 } else if (chan->blocking) {
00421 pthread_kill(chan->blocker, SIGURG);
00422 }
00423 ast_mutex_unlock(&chan->lock);
00424 return 0;
00425 }
00426
00427 int ast_queue_hangup(struct ast_channel *chan)
00428 {
00429 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
00430 chan->_softhangup |= AST_SOFTHANGUP_DEV;
00431 return ast_queue_frame(chan, &f);
00432 }
00433
00434 int ast_queue_control(struct ast_channel *chan, int control)
00435 {
00436 struct ast_frame f = { AST_FRAME_CONTROL, };
00437 f.subclass = control;
00438 return ast_queue_frame(chan, &f);
00439 }
00440
00441 int ast_channel_defer_dtmf(struct ast_channel *chan)
00442 {
00443 int pre = 0;
00444 if (chan) {
00445 pre = chan->deferdtmf;
00446 chan->deferdtmf = 1;
00447 }
00448 return pre;
00449 }
00450
00451 void ast_channel_undefer_dtmf(struct ast_channel *chan)
00452 {
00453 if (chan)
00454 chan->deferdtmf = 0;
00455 }
00456
00457 struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev)
00458 {
00459
00460 struct ast_channel *l, *ret;
00461 int retries = 0;
00462 retry:
00463 ret=NULL;
00464 ast_mutex_lock(&chlock);
00465 l = channels;
00466 if (!prev) {
00467 if (l) {
00468 if (ast_mutex_trylock(&l->lock)) {
00469 if (retries < 10)
00470 ast_log(LOG_DEBUG, "Avoiding initial deadlock for '%s'\n", l->name);
00471 else
00472 ast_log(LOG_WARNING, "Avoided initial deadlock for '%s', %d retries!\n", l->name, retries);
00473 ast_mutex_unlock(&chlock);
00474 if (retries < 10) {
00475 usleep(1);
00476 retries++;
00477 goto retry;
00478 } else
00479 return NULL;
00480 }
00481 }
00482 ast_mutex_unlock(&chlock);
00483 return l;
00484 }
00485 while(l) {
00486 if (l == prev)
00487 ret = l->next;
00488 l = l->next;
00489 }
00490 if (ret) {
00491 if (ast_mutex_trylock(&ret->lock)) {
00492 if (retries < 10)
00493 ast_log(LOG_DEBUG, "Avoiding deadlock for '%s'\n", ret->name);
00494 else
00495 ast_log(LOG_WARNING, "Avoided deadlock for '%s', %d retries!\n", ret->name, retries);
00496 ast_mutex_unlock(&chlock);
00497 if (retries < 10) {
00498 usleep(1);
00499 retries++;
00500 goto retry;
00501 } else
00502 return NULL;
00503 }
00504 }
00505 ast_mutex_unlock(&chlock);
00506 return ret;
00507
00508 }
00509
00510 struct ast_channel *ast_get_channel_by_name_locked(char *channame)
00511 {
00512 struct ast_channel *chan;
00513 chan = ast_channel_walk_locked(NULL);
00514 while(chan) {
00515 if (!strcasecmp(chan->name, channame))
00516 return chan;
00517 ast_mutex_unlock(&chan->lock);
00518 chan = ast_channel_walk_locked(chan);
00519 }
00520 return NULL;
00521 }
00522
00523 int ast_safe_sleep_conditional( struct ast_channel *chan, int ms,
00524 int (*cond)(void*), void *data )
00525 {
00526 struct ast_frame *f;
00527
00528 while(ms > 0) {
00529 if( cond && ((*cond)(data) == 0 ) )
00530 return 0;
00531 ms = ast_waitfor(chan, ms);
00532 if (ms <0)
00533 return -1;
00534 if (ms > 0) {
00535 f = ast_read(chan);
00536 if (!f)
00537 return -1;
00538 ast_frfree(f);
00539 }
00540 }
00541 return 0;
00542 }
00543
00544 int ast_safe_sleep(struct ast_channel *chan, int ms)
00545 {
00546 struct ast_frame *f;
00547 while(ms > 0) {
00548 ms = ast_waitfor(chan, ms);
00549 if (ms <0)
00550 return -1;
00551 if (ms > 0) {
00552 f = ast_read(chan);
00553 if (!f)
00554 return -1;
00555 ast_frfree(f);
00556 }
00557 }
00558 return 0;
00559 }
00560
00561 void ast_channel_free(struct ast_channel *chan)
00562 {
00563 struct ast_channel *last=NULL, *cur;
00564 int fd;
00565 struct ast_var_t *vardata;
00566 struct ast_frame *f, *fp;
00567 struct varshead *headp;
00568 char name[AST_CHANNEL_NAME];
00569
00570 headp=&chan->varshead;
00571
00572 ast_mutex_lock(&chlock);
00573 cur = channels;
00574 while(cur) {
00575 if (cur == chan) {
00576 if (last)
00577 last->next = cur->next;
00578 else
00579 channels = cur->next;
00580 break;
00581 }
00582 last = cur;
00583 cur = cur->next;
00584 }
00585 if (!cur)
00586 ast_log(LOG_WARNING, "Unable to find channel in list\n");
00587 else {
00588
00589
00590 ast_mutex_lock(&cur->lock);
00591 ast_mutex_unlock(&cur->lock);
00592 }
00593 if (chan->pvt->pvt)
00594 ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
00595
00596 strncpy(name, chan->name, sizeof(name)-1);
00597
00598
00599 if (chan->monitor) {
00600 chan->monitor->stop( chan, 0 );
00601 }
00602
00603
00604 if (chan->pvt->readtrans)
00605 ast_translator_free_path(chan->pvt->readtrans);
00606 if (chan->pvt->writetrans)
00607 ast_translator_free_path(chan->pvt->writetrans);
00608 if (chan->pbx)
00609 ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
00610 if (chan->dnid)
00611 free(chan->dnid);
00612 if (chan->callerid)
00613 free(chan->callerid);
00614 if (chan->ani)
00615 free(chan->ani);
00616 if (chan->rdnis)
00617 free(chan->rdnis);
00618 ast_mutex_destroy(&chan->lock);
00619
00620 if ((fd = chan->pvt->alertpipe[0]) > -1)
00621 close(fd);
00622 if ((fd = chan->pvt->alertpipe[1]) > -1)
00623 close(fd);
00624 if ((fd = chan->timingfd) > -1)
00625 close(fd);
00626 f = chan->pvt->readq;
00627 chan->pvt->readq = NULL;
00628 while(f) {
00629 fp = f;
00630 f = f->next;
00631 ast_frfree(fp);
00632 }
00633
00634
00635
00636
00637 while (!AST_LIST_EMPTY(headp)) {
00638 vardata = AST_LIST_FIRST(headp);
00639 AST_LIST_REMOVE_HEAD(headp, entries);
00640
00641 ast_var_delete(vardata);
00642 }
00643
00644
00645 free(chan->pvt);
00646 chan->pvt = NULL;
00647 free(chan);
00648 ast_mutex_unlock(&chlock);
00649
00650 ast_device_state_changed(name);
00651 }
00652
00653 int ast_softhangup_nolock(struct ast_channel *chan, int cause)
00654 {
00655 int res = 0;
00656 struct ast_frame f = { AST_FRAME_NULL };
00657 if (option_debug)
00658 ast_log(LOG_DEBUG, "Soft-Hanging up channel '%s'\n", chan->name);
00659
00660 chan->_softhangup |= cause;
00661 ast_queue_frame(chan, &f);
00662
00663 if (chan->blocking)
00664 pthread_kill(chan->blocker, SIGURG);
00665 return res;
00666 }
00667
00668 int ast_softhangup(struct ast_channel *chan, int cause)
00669 {
00670 int res;
00671 ast_mutex_lock(&chan->lock);
00672 res = ast_softhangup_nolock(chan, cause);
00673 ast_mutex_unlock(&chan->lock);
00674 return res;
00675 }
00676
00677 static void free_translation(struct ast_channel *clone)
00678 {
00679 if (clone->pvt->writetrans)
00680 ast_translator_free_path(clone->pvt->writetrans);
00681 if (clone->pvt->readtrans)
00682 ast_translator_free_path(clone->pvt->readtrans);
00683 clone->pvt->writetrans = NULL;
00684 clone->pvt->readtrans = NULL;
00685 clone->pvt->rawwriteformat = clone->nativeformats;
00686 clone->pvt->rawreadformat = clone->nativeformats;
00687 }
00688
00689 int ast_hangup(struct ast_channel *chan)
00690 {
00691 int res = 0;
00692
00693
00694 ast_mutex_lock(&chan->lock);
00695 if (chan->masq) {
00696 if (ast_do_masquerade(chan))
00697 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
00698 }
00699
00700 if (chan->masq) {
00701 ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
00702 ast_mutex_unlock(&chan->lock);
00703 return 0;
00704 }
00705
00706
00707 if (chan->masqr) {
00708 chan->zombie=1;
00709 ast_mutex_unlock(&chan->lock);
00710 return 0;
00711 }
00712 free_translation(chan);
00713 if (chan->stream)
00714 ast_closestream(chan->stream);
00715 if (chan->vstream)
00716 ast_closestream(chan->vstream);
00717 if (chan->sched)
00718 sched_context_destroy(chan->sched);
00719
00720 if (chan->generatordata)
00721 chan->generator->release(chan, chan->generatordata);
00722 chan->generatordata = NULL;
00723 chan->generator = NULL;
00724 if (chan->cdr) {
00725
00726 ast_cdr_end(chan->cdr);
00727
00728 ast_cdr_post(chan->cdr);
00729 ast_cdr_free(chan->cdr);
00730 }
00731 if (chan->blocking) {
00732 ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
00733 "is blocked by thread %ld in procedure %s! Expect a failure\n",
00734 (long)pthread_self(), chan->name, (long)chan->blocker, chan->blockproc);
00735 CRASH;
00736 }
00737 if (!chan->zombie) {
00738 if (option_debug)
00739 ast_log(LOG_DEBUG, "Hanging up channel '%s'\n", chan->name);
00740 if (chan->pvt->hangup)
00741 res = chan->pvt->hangup(chan);
00742 } else
00743 if (option_debug)
00744 ast_log(LOG_DEBUG, "Hanging up zombie '%s'\n", chan->name);
00745
00746 ast_mutex_unlock(&chan->lock);
00747 manager_event(EVENT_FLAG_CALL, "Hangup",
00748 "Channel: %s\r\n"
00749 "Uniqueid: %s\r\n"
00750 "Cause: %i\r\n",
00751 chan->name, chan->uniqueid, chan->hangupcause);
00752 ast_channel_free(chan);
00753 return res;
00754 }
00755
00756 void ast_channel_unregister(char *type)
00757 {
00758 struct chanlist *chan, *last=NULL;
00759 if (option_debug)
00760 ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", type);
00761 if (ast_mutex_lock(&chlock)) {
00762 ast_log(LOG_WARNING, "Unable to lock channel list\n");
00763 return;
00764 }
00765 if (option_verbose > 1)
00766 ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", type);
00767
00768 chan = backends;
00769 while(chan) {
00770 if (!strcasecmp(chan->type, type)) {
00771 if (last)
00772 last->next = chan->next;
00773 else
00774 backends = backends->next;
00775 free(chan);
00776 ast_mutex_unlock(&chlock);
00777 return;
00778 }
00779 last = chan;
00780 chan = chan->next;
00781 }
00782 ast_mutex_unlock(&chlock);
00783 }
00784
00785 int ast_answer(struct ast_channel *chan)
00786 {
00787 int res = 0;
00788 ast_mutex_lock(&chan->lock);
00789
00790 if (chan->zombie || ast_check_hangup(chan)) {
00791 ast_mutex_unlock(&chan->lock);
00792 return -1;
00793 }
00794 switch(chan->_state) {
00795 case AST_STATE_RINGING:
00796 case AST_STATE_RING:
00797 if (chan->pvt->answer)
00798 res = chan->pvt->answer(chan);
00799 ast_setstate(chan, AST_STATE_UP);
00800 if (chan->cdr)
00801 ast_cdr_answer(chan->cdr);
00802 ast_mutex_unlock(&chan->lock);
00803 return res;
00804 break;
00805 case AST_STATE_UP:
00806 if (chan->cdr)
00807 ast_cdr_answer(chan->cdr);
00808 break;
00809 }
00810 ast_mutex_unlock(&chan->lock);
00811 return 0;
00812 }
00813
00814
00815
00816 void ast_deactivate_generator(struct ast_channel *chan)
00817 {
00818 ast_mutex_lock(&chan->lock);
00819 if (chan->generatordata) {
00820 if (chan->generator && chan->generator->release)
00821 chan->generator->release(chan, chan->generatordata);
00822 chan->generatordata = NULL;
00823 chan->generator = NULL;
00824 chan->writeinterrupt = 0;
00825 ast_settimeout(chan, 0, NULL, NULL);
00826 }
00827 ast_mutex_unlock(&chan->lock);
00828 }
00829
00830 static int generator_force(void *data)
00831 {
00832
00833 void *tmp;
00834 int res;
00835 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
00836 struct ast_channel *chan = data;
00837 tmp = chan->generatordata;
00838 chan->generatordata = NULL;
00839 generate = chan->generator->generate;
00840 res = generate(chan, tmp, 0, 160);
00841 chan->generatordata = tmp;
00842 if (res) {
00843 ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
00844 ast_deactivate_generator(chan);
00845 }
00846 return 0;
00847 }
00848
00849 int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
00850 {
00851 int res = 0;
00852 ast_mutex_lock(&chan->lock);
00853 if (chan->generatordata) {
00854 if (chan->generator && chan->generator->release)
00855 chan->generator->release(chan, chan->generatordata);
00856 chan->generatordata = NULL;
00857 }
00858 ast_prod(chan);
00859 if ((chan->generatordata = gen->alloc(chan, params))) {
00860 ast_settimeout(chan, 160, generator_force, chan);
00861 chan->generator = gen;
00862 } else {
00863 res = -1;
00864 }
00865 ast_mutex_unlock(&chan->lock);
00866 return res;
00867 }
00868
00869 int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
00870 {
00871
00872 struct timeval start, now;
00873 int res;
00874 int x, y;
00875 int winner = -1;
00876 int spoint;
00877 struct pollfd *pfds;
00878
00879 pfds = alloca(sizeof(struct pollfd) * n);
00880 if (!pfds) {
00881 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
00882 return -1;
00883 }
00884 if (*ms > 0)
00885 gettimeofday(&start, NULL);
00886 y = 0;
00887 for (x=0;x<n;x++) {
00888 if (fds[x] > -1) {
00889 pfds[y].fd = fds[x];
00890 pfds[y].events = POLLIN | POLLPRI;
00891 y++;
00892 }
00893 }
00894 res = poll(pfds, y, *ms);
00895 if (res < 0) {
00896
00897 if (errno != EINTR)
00898 *ms = -1;
00899 else
00900 *ms = 0;
00901 return -1;
00902 }
00903 spoint = 0;
00904 for (x=0;x<n;x++) {
00905 if (fds[x] > -1) {
00906 if ((res = ast_fdisset(pfds, fds[x], y, &spoint))) {
00907 winner = fds[x];
00908 if (exception) {
00909 if (res & POLLPRI)
00910 *exception = -1;
00911 else
00912 *exception = 0;
00913 }
00914 }
00915 }
00916 }
00917 if (*ms > 0) {
00918 long passed;
00919 gettimeofday(&now, NULL);
00920 passed = (now.tv_sec - start.tv_sec) * 1000;
00921 passed += (now.tv_usec - start.tv_usec) / 1000;
00922 if (passed <= *ms)
00923 *ms -= passed;
00924 else
00925 *ms = 0;
00926 }
00927 return winner;
00928 }
00929
00930 struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
00931 int *exception, int *outfd, int *ms)
00932 {
00933
00934 struct timeval start, end;
00935 struct pollfd *pfds;
00936 int res;
00937 long rms;
00938 int x, y, max;
00939 int spoint;
00940 time_t now = 0;
00941 long whentohangup = 0, havewhen = 0, diff;
00942 struct ast_channel *winner = NULL;
00943
00944 pfds = alloca(sizeof(struct pollfd) * (n * AST_MAX_FDS + nfds));
00945 if (!pfds) {
00946 ast_log(LOG_WARNING, "alloca failed! bad things will happen.\n");
00947 *outfd = -1;
00948 return NULL;
00949 }
00950
00951 if (outfd)
00952 *outfd = -99999;
00953 if (exception)
00954 *exception = 0;
00955
00956
00957 for (x=0;x<n;x++) {
00958 ast_mutex_lock(&c[x]->lock);
00959 if (c[x]->whentohangup) {
00960 if (!havewhen)
00961 time(&now);
00962 diff = c[x]->whentohangup - now;
00963 if (!havewhen || (diff < whentohangup)) {
00964 havewhen++;
00965 whentohangup = diff;
00966 }
00967 }
00968 if (c[x]->masq) {
00969 if (ast_do_masquerade(c[x])) {
00970 ast_log(LOG_WARNING, "Masquerade failed\n");
00971 *ms = -1;
00972 ast_mutex_unlock(&c[x]->lock);
00973 return NULL;
00974 }
00975 }
00976 ast_mutex_unlock(&c[x]->lock);
00977 }
00978
00979 rms = *ms;
00980
00981 if (havewhen) {
00982 if ((*ms < 0) || (whentohangup * 1000 < *ms)) {
00983 rms = whentohangup * 1000;
00984 }
00985 }
00986 max = 0;
00987 for (x=0;x<n;x++) {
00988 for (y=0;y<AST_MAX_FDS;y++) {
00989 if (c[x]->fds[y] > -1) {
00990 pfds[max].fd = c[x]->fds[y];
00991 pfds[max].events = POLLIN | POLLPRI;
00992 max++;
00993 }
00994 }
00995 CHECK_BLOCKING(c[x]);
00996 }
00997 for (x=0;x<nfds; x++) {
00998 if (fds[x] > -1) {
00999 pfds[max].fd = fds[x];
01000 pfds[max].events = POLLIN | POLLPRI;
01001 max++;
01002 }
01003 }
01004 if (*ms > 0)
01005 gettimeofday(&start, NULL);
01006 res = poll(pfds, max, rms);
01007 if (res < 0) {
01008 for (x=0;x<n;x++)
01009 c[x]->blocking = 0;
01010
01011 if (errno != EINTR)
01012 *ms = -1;
01013 else {
01014
01015 #if 0
01016 *ms = 0;
01017 #endif
01018 }
01019 return NULL;
01020 }
01021
01022 if (havewhen)
01023 time(&now);
01024 spoint = 0;
01025 for (x=0;x<n;x++) {
01026 c[x]->blocking = 0;
01027 if (havewhen && c[x]->whentohangup && (now > c[x]->whentohangup)) {
01028 c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
01029 if (!winner)
01030 winner = c[x];
01031 }
01032 for (y=0;y<AST_MAX_FDS;y++) {
01033 if (c[x]->fds[y] > -1) {
01034 if ((res = ast_fdisset(pfds, c[x]->fds[y], max, &spoint))) {
01035 if (res & POLLPRI)
01036 c[x]->exception = -1;
01037 else
01038 c[x]->exception = 0;
01039 c[x]->fdno = y;
01040 winner = c[x];
01041 }
01042 }
01043 }
01044 }
01045 for (x=0;x<nfds;x++) {
01046 if (fds[x] > -1) {
01047 if ((res = ast_fdisset(pfds, fds[x], max, &spoint))) {
01048 if (outfd)
01049 *outfd = fds[x];
01050 if (exception) {
01051 if (res & POLLPRI)
01052 *exception = -1;
01053 else
01054 *exception = 0;
01055 }
01056 winner = NULL;
01057 }
01058 }
01059 }
01060 if (*ms > 0) {
01061 long diff;
01062 gettimeofday(&end, NULL);
01063 diff = (end.tv_sec - start.tv_sec) * 1000;
01064 diff += (end.tv_usec - start.tv_usec) / 1000;
01065 if (diff < *ms)
01066 *ms -= diff;
01067 else
01068 *ms = 0;
01069 }
01070 return winner;
01071 }
01072
01073 struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
01074 {
01075 return ast_waitfor_nandfds(c, n, NULL, 0, NULL, NULL, ms);
01076 }
01077
01078 int ast_waitfor(struct ast_channel *c, int ms)
01079 {
01080 struct ast_channel *chan;
01081 int oldms = ms;
01082 chan = ast_waitfor_n(&c, 1, &ms);
01083 if (ms < 0) {
01084 if (oldms < 0)
01085 return 0;
01086 else
01087 return -1;
01088 }
01089 return ms;
01090 }
01091
01092 int ast_waitfordigit(struct ast_channel *c, int ms)
01093 {
01094
01095 struct ast_frame *f;
01096 int result = 0;
01097
01098 if (c->zombie || ast_check_hangup(c))
01099 return -1;
01100
01101 while(ms && !result) {
01102 ms = ast_waitfor(c, ms);
01103 if (ms < 0)
01104 result = -1;
01105 else if (ms > 0) {
01106
01107 f = ast_read(c);
01108 if (f) {
01109 if (f->frametype == AST_FRAME_DTMF)
01110 result = f->subclass;
01111 ast_frfree(f);
01112 } else
01113 result = -1;
01114 }
01115 }
01116 return result;
01117 }
01118
01119 int ast_settimeout(struct ast_channel *c, int samples, int (*func)(void *data), void *data)
01120 {
01121 int res = -1;
01122 #ifdef ZAPTEL_OPTIMIZATIONS
01123 if (c->timingfd > -1) {
01124 if (!func) {
01125 samples = 0;
01126 data = 0;
01127 }
01128 ast_log(LOG_DEBUG, "Scheduling timer at %d sample intervals\n", samples);
01129 res = ioctl(c->timingfd, ZT_TIMERCONFIG, &samples);
01130 c->timingfunc = func;
01131 c->timingdata = data;
01132 }
01133 #endif
01134 return res;
01135 }
01136 int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd)
01137 {
01138 struct ast_frame *f;
01139 struct ast_channel *rchan;
01140 int outfd;
01141 int res;
01142
01143 if (c->zombie || ast_check_hangup(c))
01144 return -1;
01145
01146 while(ms) {
01147 errno = 0;
01148 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01149 if ((!rchan) && (outfd < 0) && (ms)) {
01150 if (errno == 0 || errno == EINTR)
01151 continue;
01152 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01153 return -1;
01154 } else if (outfd > -1) {
01155
01156 return 1;
01157 } else if (rchan) {
01158 f = ast_read(c);
01159 if(!f) {
01160 return -1;
01161 }
01162
01163 switch(f->frametype) {
01164 case AST_FRAME_DTMF:
01165 res = f->subclass;
01166 ast_frfree(f);
01167 return res;
01168 case AST_FRAME_CONTROL:
01169 switch(f->subclass) {
01170 case AST_CONTROL_HANGUP:
01171 ast_frfree(f);
01172 return -1;
01173 case AST_CONTROL_RINGING:
01174 case AST_CONTROL_ANSWER:
01175
01176 break;
01177 default:
01178 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01179 }
01180 case AST_FRAME_VOICE:
01181
01182 if (audiofd > -1)
01183 write(audiofd, f->data, f->datalen);
01184 }
01185
01186 ast_frfree(f);
01187 }
01188 }
01189 return 0;
01190 }
01191
01192 struct ast_frame *ast_read(struct ast_channel *chan)
01193 {
01194 struct ast_frame *f = NULL;
01195 int blah;
01196 #ifdef ZAPTEL_OPTIMIZATIONS
01197 int (*func)(void *);
01198 void *data;
01199 int res;
01200 #endif
01201 static struct ast_frame null_frame =
01202 {
01203 AST_FRAME_NULL,
01204 };
01205
01206 ast_mutex_lock(&chan->lock);
01207 if (chan->masq) {
01208 if (ast_do_masquerade(chan)) {
01209 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01210 f = NULL;
01211 } else
01212 f = &null_frame;
01213 ast_mutex_unlock(&chan->lock);
01214 return f;
01215 }
01216
01217
01218 if (chan->zombie || ast_check_hangup(chan)) {
01219 if (chan->generator)
01220 ast_deactivate_generator(chan);
01221 ast_mutex_unlock(&chan->lock);
01222 return NULL;
01223 }
01224
01225 if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) {
01226
01227 chan->dtmff.frametype = AST_FRAME_DTMF;
01228 chan->dtmff.subclass = chan->dtmfq[0];
01229
01230 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01231 ast_mutex_unlock(&chan->lock);
01232 return &chan->dtmff;
01233 }
01234
01235
01236
01237 if (chan->pvt->alertpipe[0] > -1) {
01238 read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01239 }
01240 #ifdef ZAPTEL_OPTIMIZATIONS
01241 if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01242 chan->exception = 0;
01243 blah = -1;
01244
01245 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
01246 if (res)
01247 blah = ZT_EVENT_TIMER_EXPIRED;
01248
01249 if (blah == ZT_EVENT_TIMER_PING) {
01250 #if 0
01251 ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
01252 #endif
01253 if (!chan->pvt->readq || !chan->pvt->readq->next) {
01254
01255 #if 0
01256 ast_log(LOG_NOTICE, "Sending a PONG!\n");
01257 #endif
01258 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
01259 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
01260 }
01261 }
01262 } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
01263 ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01264 func = chan->timingfunc;
01265 data = chan->timingdata;
01266 ast_mutex_unlock(&chan->lock);
01267 if (func) {
01268 #if 0
01269 ast_log(LOG_DEBUG, "Calling private function\n");
01270 #endif
01271 func(data);
01272 } else {
01273 blah = 0;
01274 ast_mutex_lock(&chan->lock);
01275 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01276 chan->timingdata = NULL;
01277 ast_mutex_unlock(&chan->lock);
01278 }
01279 f = &null_frame;
01280 return f;
01281 } else
01282 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
01283 }
01284 #endif
01285
01286 if (chan->pvt->readq) {
01287 f = chan->pvt->readq;
01288 chan->pvt->readq = f->next;
01289
01290 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01291 ast_frfree(f);
01292 f = NULL;
01293 }
01294 } else {
01295 chan->blocker = pthread_self();
01296 if (chan->exception) {
01297 if (chan->pvt->exception)
01298 f = chan->pvt->exception(chan);
01299 else {
01300 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01301 f = &null_frame;
01302 }
01303
01304 chan->exception = 0;
01305 } else
01306 if (chan->pvt->read)
01307 f = chan->pvt->read(chan);
01308 else
01309 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01310 }
01311
01312
01313 if (f && (f->frametype == AST_FRAME_VOICE)) {
01314 if (!(f->subclass & chan->nativeformats)) {
01315
01316
01317 ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n", chan->name, ast_getformatname(f->subclass), ast_getformatname(chan->nativeformats));
01318 ast_frfree(f);
01319 f = &null_frame;
01320 } else {
01321 if (chan->monitor && chan->monitor->read_stream ) {
01322 #ifndef MONITOR_CONSTANT_DELAY
01323 int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01324 if (jump >= 0) {
01325 if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01326 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01327 chan->insmpl += jump + 2 * f->samples;
01328 } else
01329 chan->insmpl+= f->samples;
01330 #else
01331 int jump = chan->outsmpl - chan->insmpl;
01332 if (jump - MONITOR_DELAY >= 0) {
01333 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01334 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01335 chan->insmpl += jump;
01336 } else
01337 chan->insmpl += f->samples;
01338 #endif
01339 if (ast_writestream(chan->monitor->read_stream, f) < 0)
01340 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01341 }
01342 if (chan->pvt->readtrans) {
01343 f = ast_translate(chan->pvt->readtrans, f, 1);
01344 if (!f)
01345 f = &null_frame;
01346 }
01347 }
01348 }
01349
01350
01351 if (!f) {
01352 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01353 if (chan->generator)
01354 ast_deactivate_generator(chan);
01355
01356 if (chan->cdr)
01357 ast_cdr_end(chan->cdr);
01358 } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01359 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01360 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01361 else
01362 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01363 f = &null_frame;
01364 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01365 if (chan->_state == AST_STATE_UP) {
01366 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
01367 f = &null_frame;
01368 }
01369
01370 ast_setstate(chan, AST_STATE_UP);
01371 ast_cdr_answer(chan->cdr);
01372 }
01373
01374
01375 if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01376
01377
01378 void *tmp;
01379 int res;
01380 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
01381 if (chan->timingfunc) {
01382 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
01383 ast_settimeout(chan, 0, NULL, NULL);
01384 }
01385 tmp = chan->generatordata;
01386 chan->generatordata = NULL;
01387 generate = chan->generator->generate;
01388 res = generate(chan, tmp, f->datalen, f->samples);
01389 chan->generatordata = tmp;
01390 if (res) {
01391 ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01392 ast_deactivate_generator(chan);
01393 }
01394 } else if (f && (f->frametype == AST_FRAME_CNG)) {
01395 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
01396 ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
01397 ast_settimeout(chan, 160, generator_force, chan);
01398 }
01399 }
01400
01401 if (chan->fin & 0x80000000)
01402 ast_frame_dump(chan->name, f, "<<");
01403 if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01404 chan->fin &= 0x80000000;
01405 else
01406 chan->fin++;
01407 ast_mutex_unlock(&chan->lock);
01408 return f;
01409 }
01410
01411 int ast_indicate(struct ast_channel *chan, int condition)
01412 {
01413 int res = -1;
01414
01415 if (chan->zombie || ast_check_hangup(chan))
01416 return -1;
01417 ast_mutex_lock(&chan->lock);
01418 if (chan->pvt->indicate)
01419 res = chan->pvt->indicate(chan, condition);
01420 ast_mutex_unlock(&chan->lock);
01421 if (!chan->pvt->indicate || res) {
01422
01423
01424
01425
01426 if (condition >= 0) {
01427 const struct tone_zone_sound *ts = NULL;
01428 switch (condition) {
01429 case AST_CONTROL_RINGING:
01430 ts = ast_get_indication_tone(chan->zone, "ring");
01431 break;
01432 case AST_CONTROL_BUSY:
01433 ts = ast_get_indication_tone(chan->zone, "busy");
01434 break;
01435 case AST_CONTROL_CONGESTION:
01436 ts = ast_get_indication_tone(chan->zone, "congestion");
01437 break;
01438 }
01439 if (ts && ts->data[0]) {
01440 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01441 ast_playtones_start(chan,0,ts->data, 1);
01442 res = 0;
01443 } else if (condition == AST_CONTROL_PROGRESS) {
01444
01445 } else if (condition == AST_CONTROL_PROCEEDING) {
01446
01447 } else {
01448
01449 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01450 res = -1;
01451 }
01452 }
01453 else ast_playtones_stop(chan);
01454 }
01455 return res;
01456 }
01457
01458 int ast_recvchar(struct ast_channel *chan, int timeout)
01459 {
01460 int res,ourto,c;
01461 struct ast_frame *f;
01462
01463 ourto = timeout;
01464 for(;;)
01465 {
01466 if (ast_check_hangup(chan)) return -1;
01467 res = ast_waitfor(chan,ourto);
01468 if (res <= 0)
01469 {
01470 return 0;
01471 }
01472 ourto = res;
01473 f = ast_read(chan);
01474 if (f == NULL) return -1;
01475 if ((f->frametype == AST_FRAME_CONTROL) &&
01476 (f->subclass == AST_CONTROL_HANGUP)) return -1;
01477 if (f->frametype == AST_FRAME_TEXT)
01478 {
01479 c = *((char *)f->data);
01480 ast_frfree(f);
01481 return(c);
01482 }
01483 ast_frfree(f);
01484 }
01485 }
01486
01487 int ast_sendtext(struct ast_channel *chan, char *text)
01488 {
01489 int res = 0;
01490
01491 if (chan->zombie || ast_check_hangup(chan))
01492 return -1;
01493 CHECK_BLOCKING(chan);
01494 if (chan->pvt->send_text)
01495 res = chan->pvt->send_text(chan, text);
01496 chan->blocking = 0;
01497 return res;
01498 }
01499
01500 static int do_senddigit(struct ast_channel *chan, char digit)
01501 {
01502 int res = -1;
01503
01504 if (chan->pvt->send_digit)
01505 res = chan->pvt->send_digit(chan, digit);
01506 if (!chan->pvt->send_digit || res) {
01507
01508
01509
01510
01511 static const char* dtmf_tones[] = {
01512 "!941+1336/100,!0/100",
01513 "!697+1209/100,!0/100",
01514 "!697+1336/100,!0/100",
01515 "!697+1477/100,!0/100",
01516 "!770+1209/100,!0/100",
01517 "!770+1336/100,!0/100",
01518 "!770+1477/100,!0/100",
01519 "!852+1209/100,!0/100",
01520 "!852+1336/100,!0/100",
01521 "!852+1477/100,!0/100",
01522 "!697+1633/100,!0/100",
01523 "!770+1633/100,!0/100",
01524 "!852+1633/100,!0/100",
01525 "!941+1633/100,!0/100",
01526 "!941+1209/100,!0/100",
01527 "!941+1477/100,!0/100" };
01528 if (digit >= '0' && digit <='9')
01529 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
01530 else if (digit >= 'A' && digit <= 'D')
01531 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
01532 else if (digit == '*')
01533 ast_playtones_start(chan,0,dtmf_tones[14], 0);
01534 else if (digit == '#')
01535 ast_playtones_start(chan,0,dtmf_tones[15], 0);
01536 else {
01537
01538 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
01539 }
01540 }
01541 return 0;
01542 }
01543
01544 int ast_senddigit(struct ast_channel *chan, char digit)
01545 {
01546 return do_senddigit(chan, digit);
01547 }
01548
01549 int ast_prod(struct ast_channel *chan)
01550 {
01551 struct ast_frame a = { AST_FRAME_VOICE };
01552 char nothing[128];
01553
01554 if (chan->_state != AST_STATE_UP) {
01555 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01556 a.subclass = chan->pvt->rawwriteformat;
01557 a.data = nothing + AST_FRIENDLY_OFFSET;
01558 if (ast_write(chan, &a))
01559 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01560 }
01561 return 0;
01562 }
01563
01564 int ast_write_video(struct ast_channel *chan, struct ast_frame *fr)
01565 {
01566 int res;
01567 if (!chan->pvt->write_video)
01568 return 0;
01569 res = ast_write(chan, fr);
01570 if (!res)
01571 res = 1;
01572 return res;
01573 }
01574
01575 int ast_write(struct ast_channel *chan, struct ast_frame *fr)
01576 {
01577 int res = -1;
01578 struct ast_frame *f = NULL;
01579
01580 ast_mutex_lock(&chan->lock);
01581 if (chan->zombie || ast_check_hangup(chan)) {
01582 ast_mutex_unlock(&chan->lock);
01583 return -1;
01584 }
01585
01586 if (chan->masq) {
01587 if (ast_do_masquerade(chan)) {
01588 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01589 ast_mutex_unlock(&chan->lock);
01590 return -1;
01591 }
01592 }
01593 if (chan->masqr) {
01594 ast_mutex_unlock(&chan->lock);
01595 return 0;
01596 }
01597 if (chan->generatordata) {
01598 if (chan->writeinterrupt)
01599 ast_deactivate_generator(chan);
01600 else {
01601 ast_mutex_unlock(&chan->lock);
01602 return 0;
01603 }
01604 }
01605
01606 if (chan->fout & 0x80000000)
01607 ast_frame_dump(chan->name, fr, ">>");
01608 CHECK_BLOCKING(chan);
01609 switch(fr->frametype) {
01610 case AST_FRAME_CONTROL:
01611
01612 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01613 break;
01614 case AST_FRAME_DTMF:
01615 chan->blocking = 0;
01616 ast_mutex_unlock(&chan->lock);
01617 res = do_senddigit(chan,fr->subclass);
01618 ast_mutex_lock(&chan->lock);
01619 CHECK_BLOCKING(chan);
01620 break;
01621 case AST_FRAME_TEXT:
01622 if (chan->pvt->send_text)
01623 res = chan->pvt->send_text(chan, (char *) fr->data);
01624 else
01625 res = 0;
01626 break;
01627 case AST_FRAME_HTML:
01628 if (chan->pvt->send_html)
01629 res = chan->pvt->send_html(chan, fr->subclass, (char *) fr->data, fr->datalen);
01630 else
01631 res = 0;
01632 break;
01633 case AST_FRAME_VIDEO:
01634
01635 if (chan->pvt->write_video)
01636 res = chan->pvt->write_video(chan, fr);
01637 else
01638 res = 0;
01639 break;
01640 default:
01641 if (chan->pvt->write) {
01642 if (chan->pvt->writetrans) {
01643 f = ast_translate(chan->pvt->writetrans, fr, 0);
01644 } else
01645 f = fr;
01646 if (f) {
01647 res = chan->pvt->write(chan, f);
01648 if( chan->monitor &&
01649 chan->monitor->write_stream &&
01650 f && ( f->frametype == AST_FRAME_VOICE ) ) {
01651 #ifndef MONITOR_CONSTANT_DELAY
01652 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01653 if (jump >= 0) {
01654 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01655 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01656 chan->outsmpl += jump + 2 * f->samples;
01657 } else
01658 chan->outsmpl += f->samples;
01659 #else
01660 int jump = chan->insmpl - chan->outsmpl;
01661 if (jump - MONITOR_DELAY >= 0) {
01662 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01663 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01664 chan->outsmpl += jump;
01665 } else
01666 chan->outsmpl += f->samples;
01667 #endif
01668 if (ast_writestream(chan->monitor->write_stream, f) < 0)
01669 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01670 }
01671 } else
01672 res = 0;
01673 }
01674 }
01675 if (f && (f != fr))
01676 ast_frfree(f);
01677 chan->blocking = 0;
01678
01679 if (res < 0)
01680 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01681 else {
01682 if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01683 chan->fout &= 0x80000000;
01684 else
01685 chan->fout++;
01686 }
01687 ast_mutex_unlock(&chan->lock);
01688 return res;
01689 }
01690
01691 int ast_set_write_format(struct ast_channel *chan, int fmts)
01692 {
01693 int fmt;
01694 int native;
01695 int res;
01696
01697 ast_mutex_lock(&chan->lock);
01698 native = chan->nativeformats;
01699 fmt = fmts;
01700
01701 res = ast_translator_best_choice(&native, &fmt);
01702 if (res < 0) {
01703 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01704 ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01705 ast_mutex_unlock(&chan->lock);
01706 return -1;
01707 }
01708
01709
01710 chan->pvt->rawwriteformat = native;
01711
01712 chan->writeformat = fmt;
01713
01714 if (chan->pvt->writetrans)
01715 ast_translator_free_path(chan->pvt->writetrans);
01716
01717 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01718 if (option_debug)
01719 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01720 ast_mutex_unlock(&chan->lock);
01721 return 0;
01722 }
01723
01724 int ast_set_read_format(struct ast_channel *chan, int fmts)
01725 {
01726 int fmt;
01727 int native;
01728 int res;
01729
01730 ast_mutex_lock(&chan->lock);
01731 native = chan->nativeformats;
01732 fmt = fmts;
01733
01734 res = ast_translator_best_choice(&fmt, &native);
01735 if (res < 0) {
01736 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01737 ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01738 ast_mutex_unlock(&chan->lock);
01739 return -1;
01740 }
01741
01742
01743 chan->pvt->rawreadformat = native;
01744
01745 chan->readformat = fmt;
01746
01747 if (chan->pvt->readtrans)
01748 ast_translator_free_path(chan->pvt->readtrans);
01749
01750 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01751 if (option_debug)
01752 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n",
01753 chan->name, ast_getformatname(chan->readformat));
01754 ast_mutex_unlock(&chan->lock);
01755 return 0;
01756 }
01757
01758 struct ast_channel *__ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, char *callerid, struct outgoing_helper *oh)
01759 {
01760 int state = 0;
01761 struct ast_channel *chan;
01762 struct ast_frame *f;
01763 int res = 0;
01764 char *variable;
01765 chan = ast_request(type, format, data);
01766 if (chan) {
01767 if (oh) {
01768 char *tmp, *var;
01769
01770 if (oh->variable)
01771 variable = ast_strdupa(oh->variable);
01772 else
01773 variable = NULL;
01774 tmp = variable;
01775
01776 while( (var = strtok_r(NULL, "|", &tmp)) ) {
01777 pbx_builtin_setvar( chan, var );
01778 }
01779 if (oh->callerid && *oh->callerid)
01780 ast_set_callerid(chan, oh->callerid, 1);
01781 if (oh->account && *oh->account)
01782 ast_cdr_setaccount(chan, oh->account);
01783 }
01784 if (callerid && !ast_strlen_zero(callerid))
01785 ast_set_callerid(chan, callerid, 1);
01786
01787 if (!ast_call(chan, data, 0)) {
01788 while(timeout && (chan->_state != AST_STATE_UP)) {
01789 res = ast_waitfor(chan, timeout);
01790 if (res < 0) {
01791
01792 break;
01793 }
01794
01795 if (!res)
01796 break;
01797 if (timeout > -1)
01798 timeout = res;
01799 f = ast_read(chan);
01800 if (!f) {
01801 state = AST_CONTROL_HANGUP;
01802 res = 0;
01803 break;
01804 }
01805 if (f->frametype == AST_FRAME_CONTROL) {
01806 if (f->subclass == AST_CONTROL_RINGING)
01807 state = AST_CONTROL_RINGING;
01808 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01809 state = f->subclass;
01810 ast_frfree(f);
01811 break;
01812 } else if (f->subclass == AST_CONTROL_ANSWER) {
01813 state = f->subclass;
01814 ast_frfree(f);
01815 break;
01816 } else if (f->subclass == AST_CONTROL_PROGRESS) {
01817
01818 } else if (f->subclass == -1) {
01819
01820 } else {
01821 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01822 }
01823 }
01824 ast_frfree(f);
01825 }
01826 } else
01827 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01828 } else
01829 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01830 if (chan) {
01831
01832 if (oh) {
01833 if (oh->context && *oh->context)
01834 strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01835 if (oh->exten && *oh->exten)
01836 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01837 chan->priority = oh->priority;
01838 }
01839 if (chan->_state == AST_STATE_UP)
01840 state = AST_CONTROL_ANSWER;
01841 }
01842 if (outstate)
01843 *outstate = state;
01844 if (chan && res <= 0) {
01845 if (!chan->cdr) {
01846 chan->cdr = ast_cdr_alloc();
01847 if (chan->cdr)
01848 ast_cdr_init(chan->cdr, chan);
01849 }
01850 if (chan->cdr) {
01851 char tmp[256];
01852 snprintf(tmp, 256, "%s/%s", type, (char *)data);
01853 ast_cdr_setapp(chan->cdr,"Dial",tmp);
01854 ast_cdr_update(chan);
01855 ast_cdr_start(chan->cdr);
01856 ast_cdr_end(chan->cdr);
01857
01858 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01859 ast_cdr_failed(chan->cdr);
01860 } else
01861 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01862 ast_hangup(chan);
01863 chan = NULL;
01864 }
01865 return chan;
01866 }
01867
01868 struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, char *callerid)
01869 {
01870 return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL);
01871 }
01872
01873 struct ast_channel *ast_request(char *type, int format, void *data)
01874 {
01875 struct chanlist *chan;
01876 struct ast_channel *c = NULL;
01877 int capabilities;
01878 int fmt;
01879 int res;
01880 if (ast_mutex_lock(&chlock)) {
01881 ast_log(LOG_WARNING, "Unable to lock channel list\n");
01882 return NULL;
01883 }
01884 chan = backends;
01885 while(chan) {
01886 if (!strcasecmp(type, chan->type)) {
01887 capabilities = chan->capabilities;
01888 fmt = format;
01889 res = ast_translator_best_choice(&fmt, &capabilities);
01890 if (res < 0) {
01891 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01892 ast_mutex_unlock(&chlock);
01893 return NULL;
01894 }
01895 ast_mutex_unlock(&chlock);
01896 if (chan->requester)
01897 c = chan->requester(type, capabilities, data);
01898 if (c) {
01899 if (c->_state == AST_STATE_DOWN) {
01900 manager_event(EVENT_FLAG_CALL, "Newchannel",
01901 "Channel: %s\r\n"
01902 "State: %s\r\n"
01903 "CallerID: %s\r\n"
01904 "Uniqueid: %s\r\n",
01905 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01906 }
01907 }
01908 return c;
01909 }
01910 chan = chan->next;
01911 }
01912 if (!chan)
01913 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01914 ast_mutex_unlock(&chlock);
01915 return c;
01916 }
01917
01918 int ast_parse_device_state(char *device)
01919 {
01920 char name[AST_CHANNEL_NAME] = "";
01921 char *cut;
01922 struct ast_channel *chan;
01923
01924 chan = ast_channel_walk_locked(NULL);
01925 while (chan) {
01926 strncpy(name, chan->name, sizeof(name)-1);
01927 ast_mutex_unlock(&chan->lock);
01928 cut = strchr(name,'-');
01929 if (cut)
01930 *cut = 0;
01931 if (!strcmp(name, device))
01932 return AST_DEVICE_INUSE;
01933 chan = ast_channel_walk_locked(chan);
01934 }
01935 return AST_DEVICE_UNKNOWN;
01936 }
01937
01938 int ast_device_state(char *device)
01939 {
01940 char tech[AST_MAX_EXTENSION] = "";
01941 char *number;
01942 struct chanlist *chanls;
01943 int res = 0;
01944
01945 strncpy(tech, device, sizeof(tech)-1);
01946 number = strchr(tech, '/');
01947 if (!number) {
01948 return AST_DEVICE_INVALID;
01949 }
01950 *number = 0;
01951 number++;
01952
01953 if (ast_mutex_lock(&chlock)) {
01954 ast_log(LOG_WARNING, "Unable to lock channel list\n");
01955 return -1;
01956 }
01957 chanls = backends;
01958 while(chanls) {
01959 if (!strcasecmp(tech, chanls->type)) {
01960 ast_mutex_unlock(&chlock);
01961 if (!chanls->devicestate)
01962 return ast_parse_device_state(device);
01963 else {
01964 res = chanls->devicestate(number);
01965 if (res == AST_DEVICE_UNKNOWN)
01966 return ast_parse_device_state(device);
01967 else
01968 return res;
01969 }
01970 }
01971 chanls = chanls->next;
01972 }
01973 ast_mutex_unlock(&chlock);
01974 return AST_DEVICE_INVALID;
01975 }
01976
01977 int ast_call(struct ast_channel *chan, char *addr, int timeout)
01978 {
01979
01980
01981
01982 int res = -1;
01983
01984 ast_mutex_lock(&chan->lock);
01985 if (!chan->zombie && !ast_check_hangup(chan))
01986 if (chan->pvt->call)
01987 res = chan->pvt->call(chan, addr, timeout);
01988 ast_mutex_unlock(&chan->lock);
01989 return res;
01990 }
01991
01992 int ast_transfer(struct ast_channel *chan, char *dest)
01993 {
01994
01995
01996
01997 int res = -1;
01998
01999 ast_mutex_lock(&chan->lock);
02000 if (!chan->zombie && !ast_check_hangup(chan)) {
02001 if (chan->pvt->transfer) {
02002 res = chan->pvt->transfer(chan, dest);
02003 if (!res)
02004 res = 1;
02005 } else
02006 res = 0;
02007 }
02008 ast_mutex_unlock(&chan->lock);
02009 return res;
02010 }
02011
02012 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
02013 {
02014 int pos=0;
02015 int to = ftimeout;
02016 int d;
02017
02018
02019 if (c->zombie || ast_check_hangup(c))
02020 return -1;
02021 if (!len)
02022 return -1;
02023 do {
02024 if (c->stream) {
02025 d = ast_waitstream(c, AST_DIGIT_ANY);
02026 ast_stopstream(c);
02027 usleep(1000);
02028 if (!d)
02029 d = ast_waitfordigit(c, to);
02030 } else {
02031 d = ast_waitfordigit(c, to);
02032 }
02033 if (d < 0)
02034 return -1;
02035 if (d == 0) {
02036 s[pos]='\0';
02037 return 1;
02038 }
02039 if (!strchr(enders, d))
02040 s[pos++] = d;
02041 if (strchr(enders, d) || (pos >= len)) {
02042 s[pos]='\0';
02043 return 0;
02044 }
02045 to = timeout;
02046 } while(1);
02047
02048 return 0;
02049 }
02050
02051 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
02052 {
02053 int pos=0;
02054 int to = ftimeout;
02055 int d;
02056
02057 if (c->zombie || ast_check_hangup(c))
02058 return -1;
02059 if (!len)
02060 return -1;
02061 do {
02062 if (c->stream) {
02063 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02064 ast_stopstream(c);
02065 usleep(1000);
02066 if (!d)
02067 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02068 } else {
02069 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02070 }
02071 if (d < 0)
02072 return -1;
02073 if (d == 0) {
02074 s[pos]='\0';
02075 return 1;
02076 }
02077 if (d == 1) {
02078 s[pos]='\0';
02079 return 2;
02080 }
02081 if (!strchr(enders, d))
02082 s[pos++] = d;
02083 if (strchr(enders, d) || (pos >= len)) {
02084 s[pos]='\0';
02085 return 0;
02086 }
02087 to = timeout;
02088 } while(1);
02089
02090 return 0;
02091 }
02092
02093 int ast_channel_supports_html(struct ast_channel *chan)
02094 {
02095 if (chan->pvt->send_html)
02096 return 1;
02097 return 0;
02098 }
02099
02100 int ast_channel_sendhtml(struct ast_channel *chan, int subclass, char *data, int datalen)
02101 {
02102 if (chan->pvt->send_html)
02103 return chan->pvt->send_html(chan, subclass, data, datalen);
02104 return -1;
02105 }
02106
02107 int ast_channel_sendurl(struct ast_channel *chan, char *url)
02108 {
02109 if (chan->pvt->send_html)
02110 return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
02111 return -1;
02112 }
02113
02114 int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
02115 {
02116 int peerf;
02117 int chanf;
02118 int res;
02119 ast_mutex_lock(&peer->lock);
02120 peerf = peer->nativeformats;
02121 ast_mutex_unlock(&peer->lock);
02122 ast_mutex_lock(&chan->lock);
02123 chanf = chan->nativeformats;
02124 ast_mutex_unlock(&chan->lock);
02125 res = ast_translator_best_choice(&peerf, &chanf);
02126 if (res < 0) {
02127 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02128 return -1;
02129 }
02130
02131 res = ast_set_read_format(chan, peerf);
02132 if (res < 0) {
02133 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02134 return -1;
02135 }
02136
02137 res = ast_set_write_format(peer, peerf);
02138 if (res < 0) {
02139 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02140 return -1;
02141 }
02142
02143 peerf = peer->nativeformats;
02144 chanf = chan->nativeformats;
02145 res = ast_translator_best_choice(&chanf, &peerf);
02146 if (res < 0) {
02147 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02148 return -1;
02149 }
02150
02151 res = ast_set_write_format(chan, chanf);
02152 if (res < 0) {
02153 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02154 return -1;
02155 }
02156
02157 res = ast_set_read_format(peer, chanf);
02158 if (res < 0) {
02159 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02160 return -1;
02161 }
02162 return 0;
02163 }
02164
02165 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
02166 {
02167 struct ast_frame null = { AST_FRAME_NULL, };
02168 int res = -1;
02169 ast_mutex_lock(&original->lock);
02170 while(ast_mutex_trylock(&clone->lock)) {
02171 ast_mutex_unlock(&original->lock);
02172 usleep(1);
02173 ast_mutex_lock(&original->lock);
02174 }
02175 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02176 clone->name, original->name);
02177 if (original->masq) {
02178 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
02179 original->masq->name, original->name);
02180 } else if (clone->masqr) {
02181 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
02182 clone->name, clone->masqr->name);
02183 } else {
02184 original->masq = clone;
02185 clone->masqr = original;
02186 ast_queue_frame(original, &null);
02187 ast_queue_frame(clone, &null);
02188 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02189 res = 0;
02190 }
02191 ast_mutex_unlock(&clone->lock);
02192 ast_mutex_unlock(&original->lock);
02193 return res;
02194 }
02195
02196 void ast_change_name(struct ast_channel *chan, char *newname)
02197 {
02198 char tmp[256];
02199 strncpy(tmp, chan->name, sizeof(tmp) - 1);
02200 strncpy(chan->name, newname, sizeof(chan->name) - 1);
02201 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
02202 }
02203
02204 int ast_do_masquerade(struct ast_channel *original)
02205 {
02206 int x,i;
02207 int res=0;
02208 int origstate;
02209 char *tmp;
02210 struct ast_var_t *varptr;
02211 struct ast_frame *cur, *prev;
02212 struct ast_channel_pvt *p;
02213 struct ast_channel *clone = original->masq;
02214 int rformat = original->readformat;
02215 int wformat = original->writeformat;
02216 char newn[100];
02217 char orig[100];
02218 char masqn[100];
02219 char zombn[100];
02220
02221 #if 1
02222 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
02223 clone->name, clone->_state, original->name, original->_state);
02224 #endif
02225
02226
02227
02228
02229
02230
02231 ast_mutex_lock(&clone->lock);
02232
02233 ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock);
02234
02235
02236
02237 free_translation(clone);
02238 free_translation(original);
02239
02240
02241
02242 original->masq = NULL;
02243 clone->masqr = NULL;
02244
02245
02246 strncpy(orig, original->name, sizeof(orig) - 1);
02247
02248 strncpy(newn, clone->name, sizeof(newn) - 1);
02249
02250 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
02251
02252
02253 strncpy(original->name, newn, sizeof(original->name)-1);
02254
02255
02256 strncpy(clone->name, masqn, sizeof(clone->name) - 1);
02257
02258
02259 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
02260 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
02261
02262
02263 p = original->pvt;
02264 original->pvt = clone->pvt;
02265 clone->pvt = p;
02266
02267
02268
02269 prev = NULL;
02270 cur = clone->pvt->readq;
02271 x = 0;
02272 while(cur) {
02273 x++;
02274 prev = cur;
02275 cur = cur->next;
02276 }
02277
02278
02279 if (prev) {
02280 prev->next = original->pvt->readq;
02281 original->pvt->readq = clone->pvt->readq;
02282 clone->pvt->readq = NULL;
02283 if (original->pvt->alertpipe[1] > -1) {
02284 for (i=0;i<x;i++)
02285 write(original->pvt->alertpipe[1], &x, sizeof(x));
02286 }
02287 }
02288 clone->_softhangup = AST_SOFTHANGUP_DEV;
02289
02290
02291
02292
02293
02294
02295 origstate = original->_state;
02296 original->_state = clone->_state;
02297 clone->_state = origstate;
02298
02299 if (clone->pvt->fixup){
02300 res = clone->pvt->fixup(original, clone);
02301 if (res)
02302 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
02303 }
02304
02305
02306 if (clone->pvt->hangup)
02307 res = clone->pvt->hangup(clone);
02308 if (res) {
02309 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
02310 ast_mutex_unlock(&clone->lock);
02311 return -1;
02312 }
02313
02314 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
02315
02316 strncpy(clone->name, zombn, sizeof(clone->name) - 1);
02317 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
02318
02319
02320 original->type = clone->type;
02321
02322
02323 strncpy(original->language, clone->language, sizeof(original->language));
02324
02325
02326 for (x=0;x<AST_MAX_FDS;x++) {
02327 original->fds[x] = clone->fds[x];
02328 }
02329
02330
02331 varptr = original->varshead.first;
02332 if (varptr) {
02333 while(varptr->entries.next) {
02334 varptr = varptr->entries.next;
02335 }
02336 varptr->entries.next = clone->varshead.first;
02337 } else {
02338 original->varshead.first = clone->varshead.first;
02339 }
02340 clone->varshead.first = NULL;
02341
02342 original->adsicpe = clone->adsicpe;
02343
02344
02345
02346
02347
02348 original->exception = clone->exception;
02349 original->fdno = clone->fdno;
02350
02351
02352
02353
02354
02355
02356
02357 tmp = original->dnid;
02358 original->dnid = clone->dnid;
02359 clone->dnid = tmp;
02360
02361 tmp = original->callerid;
02362 original->callerid = clone->callerid;
02363 clone->callerid = tmp;
02364
02365
02366 original->fds[AST_MAX_FDS - 2] = original->timingfd;
02367
02368
02369 original->nativeformats = clone->nativeformats;
02370
02371
02372
02373
02374
02375 ast_set_write_format(original, wformat);
02376
02377
02378 ast_set_read_format(original, rformat);
02379
02380
02381 strncpy(original->musicclass, clone->musicclass, sizeof(original->musicclass) - 1);
02382
02383 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
02384
02385
02386
02387 if (original->pvt->fixup) {
02388 res = original->pvt->fixup(clone, original);
02389 if (res) {
02390 ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
02391 original->type, original->name);
02392 ast_mutex_unlock(&clone->lock);
02393 return -1;
02394 }
02395 } else
02396 ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n",
02397 original->type, original->name);
02398
02399
02400
02401
02402 if (clone->zombie) {
02403 ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
02404 ast_mutex_unlock(&clone->lock);
02405 ast_channel_free(clone);
02406 manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
02407 } else {
02408 struct ast_frame null_frame = { AST_FRAME_NULL, };
02409 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
02410 clone->zombie=1;
02411 ast_queue_frame(clone, &null_frame);
02412 ast_mutex_unlock(&clone->lock);
02413 }
02414
02415
02416 if (original->blocking)
02417 pthread_kill(original->blocker, SIGURG);
02418 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n",
02419 original->name, original->_state);
02420 return 0;
02421 }
02422
02423 void ast_set_callerid(struct ast_channel *chan, char *callerid, int anitoo)
02424 {
02425 if (chan->callerid)
02426 free(chan->callerid);
02427 if (anitoo && chan->ani)
02428 free(chan->ani);
02429 if (callerid) {
02430 chan->callerid = strdup(callerid);
02431 if (anitoo)
02432 chan->ani = strdup(callerid);
02433 } else {
02434 chan->callerid = NULL;
02435 if (anitoo)
02436 chan->ani = NULL;
02437 }
02438 if (chan->cdr)
02439 ast_cdr_setcid(chan->cdr, chan);
02440 manager_event(EVENT_FLAG_CALL, "Newcallerid",
02441 "Channel: %s\r\n"
02442 "CallerID: %s\r\n"
02443 "Uniqueid: %s\r\n",
02444 chan->name, chan->callerid ?
02445 chan->callerid : "<Unknown>",
02446 chan->uniqueid);
02447 }
02448
02449 int ast_setstate(struct ast_channel *chan, int state)
02450 {
02451 if (chan->_state != state) {
02452 int oldstate = chan->_state;
02453 chan->_state = state;
02454 if (oldstate == AST_STATE_DOWN) {
02455 ast_device_state_changed(chan->name);
02456 manager_event(EVENT_FLAG_CALL, "Newchannel",
02457 "Channel: %s\r\n"
02458 "State: %s\r\n"
02459 "CallerID: %s\r\n"
02460 "Uniqueid: %s\r\n",
02461 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02462 } else {
02463 manager_event(EVENT_FLAG_CALL, "Newstate",
02464 "Channel: %s\r\n"
02465 "State: %s\r\n"
02466 "CallerID: %s\r\n"
02467 "Uniqueid: %s\r\n",
02468 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02469 }
02470 }
02471 return 0;
02472 }
02473
02474 static long tvdiff(struct timeval *now, struct timeval *then)
02475 {
02476 return (((now->tv_sec * 1000) + now->tv_usec / 1000) - ((then->tv_sec * 1000) + then->tv_usec / 1000));
02477 }
02478
02479 static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer, char *sound, int remain)
02480 {
02481 int res=0, min=0, sec=0,check=0;
02482
02483 check = ast_autoservice_start(peer);
02484 if(check)
02485 return;
02486
02487 if (remain > 0) {
02488 if (remain / 60 > 1) {
02489 min = remain / 60;
02490 sec = remain % 60;
02491 } else {
02492 sec = remain;
02493 }
02494 }
02495
02496 if (!strcmp(sound,"timeleft")) {
02497 res = ast_streamfile(chan, "vm-youhave", chan->language);
02498 res = ast_waitstream(chan, "");
02499 if (min) {
02500 res = ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, (char *) NULL);
02501 res = ast_streamfile(chan, "queue-minutes", chan->language);
02502 res = ast_waitstream(chan, "");
02503 }
02504 if (sec) {
02505 res = ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, (char *) NULL);
02506 res = ast_streamfile(chan, "queue-seconds", chan->language);
02507 res = ast_waitstream(chan, "");
02508 }
02509 } else {
02510 res = ast_streamfile(chan, sound, chan->language);
02511 res = ast_waitstream(chan, "");
02512 }
02513
02514 check = ast_autoservice_stop(peer);
02515 }
02516
02517 int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
02518 {
02519
02520
02521 int flags;
02522 struct ast_channel *cs[3];
02523 int to = -1;
02524 struct ast_frame *f;
02525 struct ast_channel *who = NULL;
02526 int res=0;
02527 int nativefailed=0;
02528 int firstpass;
02529 int o0nativeformats;
02530 int o1nativeformats;
02531 struct timeval start_time,precise_now;
02532 long elapsed_ms=0, time_left_ms=0;
02533 int playit=0, playitagain=1, first_time=1;
02534
02535 flags = (config->allowdisconnect_out||config->allowredirect_out ? AST_BRIDGE_DTMF_CHANNEL_0 : 0) + (config->allowdisconnect_in||config->allowredirect_in ? AST_BRIDGE_DTMF_CHANNEL_1 : 0);
02536
02537 firstpass = config->firstpass;
02538 config->firstpass = 0;
02539
02540
02541 gettimeofday(&start_time,NULL);
02542 time_left_ms = config->timelimit;
02543
02544 if (config->play_to_caller && config->start_sound && firstpass)
02545 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02546 if (config->play_to_callee && config->start_sound && firstpass)
02547 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02548
02549
02550 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1))
02551 return -1;
02552 if (c0->bridge) {
02553 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
02554 c0->name, c0->bridge->name);
02555 return -1;
02556 }
02557 if (c1->bridge) {
02558 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
02559 c1->name, c1->bridge->name);
02560 return -1;
02561 }
02562
02563
02564 c0->bridge = c1;
02565 c1->bridge = c0;
02566 cs[0] = c0;
02567 cs[1] = c1;
02568
02569 manager_event(EVENT_FLAG_CALL, "Link",
02570 "Channel1: %s\r\n"
02571 "Channel2: %s\r\n"
02572 "Uniqueid1: %s\r\n"
02573 "Uniqueid2: %s\r\n",
02574 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02575 o1nativeformats = c1->nativeformats;
02576 o0nativeformats = c0->nativeformats;
02577 for (;;) {
02578
02579 if (config->timelimit) {
02580 gettimeofday(&precise_now,NULL);
02581 elapsed_ms = tvdiff(&precise_now,&start_time);
02582 time_left_ms = config->timelimit - elapsed_ms;
02583
02584 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) {
02585
02586 if (config->warning_freq == 0) {
02587 playit = 1;
02588 first_time=0;
02589 playitagain=0;
02590 } else if (first_time) {
02591 playit = 1;
02592 first_time=0;
02593 } else {
02594 if ((time_left_ms % config->warning_freq) <= 50) {
02595 playit = 1;
02596 }
02597 }
02598 }
02599 if (time_left_ms <= 0) {
02600 if (config->play_to_caller && config->end_sound)
02601 bridge_playfile(c0,c1,config->end_sound,0);
02602 if (config->play_to_callee && config->end_sound)
02603 bridge_playfile(c1,c0,config->end_sound,0);
02604 *fo = NULL;
02605 if (who) *rc = who;
02606 res = 0;
02607 break;
02608 }
02609 if (time_left_ms >= 5000 && playit) {
02610 if (config->play_to_caller && config->warning_sound && config->play_warning)
02611 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02612 if (config->play_to_callee && config->warning_sound && config->play_warning)
02613 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02614 playit = 0;
02615 }
02616
02617 }
02618
02619 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02620 *fo = NULL;
02621 if (who) *rc = who;
02622 res = 0;
02623 ast_log(LOG_DEBUG, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",c0->name,c1->name,c0->zombie?"Yes":"No",ast_check_hangup(c0)?"Yes":"No",c1->zombie?"Yes":"No",ast_check_hangup(c1)?"Yes":"No");
02624 break;
02625 }
02626 if (c0->pvt->bridge && config->timelimit==0 &&
02627 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02628
02629 if (option_verbose > 2)
02630 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02631 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02632 c0->bridge = NULL;
02633 c1->bridge = NULL;
02634 manager_event(EVENT_FLAG_CALL, "Unlink",
02635 "Channel1: %s\r\n"
02636 "Channel2: %s\r\n"
02637 "Uniqueid1: %s\r\n"
02638 "Uniqueid2: %s\r\n",
02639 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02640 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02641 return 0;
02642 }
02643
02644
02645 if ((res != -2) && (res != -3))
02646 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02647 if (res != -3) nativefailed++;
02648 }
02649
02650 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02651 !(c0->generator || c1->generator)) {
02652 if (ast_channel_make_compatible(c0, c1)) {
02653 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
02654 manager_event(EVENT_FLAG_CALL, "Unlink",
02655 "Channel1: %s\r\n"
02656 "Channel2: %s\r\n"
02657 "Uniqueid1: %s\r\n"
02658 "Uniqueid2: %s\r\n",
02659 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02660 return -1;
02661 }
02662 o0nativeformats = c0->nativeformats;
02663 o1nativeformats = c1->nativeformats;
02664 }
02665 who = ast_waitfor_n(cs, 2, &to);
02666 if (!who) {
02667 ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
02668 continue;
02669 }
02670 f = ast_read(who);
02671 if (!f) {
02672 *fo = NULL;
02673 *rc = who;
02674 res = 0;
02675 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02676 break;
02677 }
02678
02679 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02680 *fo = f;
02681 *rc = who;
02682 res = 0;
02683 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02684 break;
02685 }
02686 if ((f->frametype == AST_FRAME_VOICE) ||
02687 (f->frametype == AST_FRAME_TEXT) ||
02688 (f->frametype == AST_FRAME_VIDEO) ||
02689 (f->frametype == AST_FRAME_IMAGE) ||
02690 (f->frametype == AST_FRAME_HTML) ||
02691 (f->frametype == AST_FRAME_DTMF)) {
02692 if ((f->frametype == AST_FRAME_DTMF) &&
02693 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02694 if ((who == c0)) {
02695 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02696 *rc = c0;
02697 *fo = f;
02698
02699 res = 0;
02700 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02701 break;
02702 } else
02703 goto tackygoto;
02704 } else
02705 if ((who == c1)) {
02706 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02707 *rc = c1;
02708 *fo = f;
02709 res = 0;
02710 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02711 break;
02712 } else
02713 goto tackygoto;
02714 }
02715 } else {
02716 #if 0
02717 ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02718 if (who == last)
02719 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02720 last = who;
02721 #endif
02722 tackygoto:
02723
02724
02725 if (who == c0)
02726 ast_write(c1, f);
02727 else
02728 ast_write(c0, f);
02729 }
02730 ast_frfree(f);
02731 } else
02732 ast_frfree(f);
02733
02734 cs[2] = cs[0];
02735 cs[0] = cs[1];
02736 cs[1] = cs[2];
02737 }
02738 c0->bridge = NULL;
02739 c1->bridge = NULL;
02740 manager_event(EVENT_FLAG_CALL, "Unlink",
02741 "Channel1: %s\r\n"
02742 "Channel2: %s\r\n"
02743 "Uniqueid1: %s\r\n"
02744 "Uniqueid2: %s\r\n",
02745 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02746 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02747 return res;
02748 }
02749
02750 int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block)
02751 {
02752 int res;
02753 if (chan->pvt->setoption) {
02754 res = chan->pvt->setoption(chan, option, data, datalen);
02755 if (res < 0)
02756 return res;
02757 } else {
02758 errno = ENOSYS;
02759 return -1;
02760 }
02761 if (block) {
02762
02763
02764 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02765 return -1;
02766 }
02767 return 0;
02768 }
02769
02770 struct tonepair_def {
02771 int freq1;
02772 int freq2;
02773 int duration;
02774 int vol;
02775 };
02776
02777 struct tonepair_state {
02778 float freq1;
02779 float freq2;
02780 float vol;
02781 int duration;
02782 int pos;
02783 int origwfmt;
02784 struct ast_frame f;
02785 unsigned char offset[AST_FRIENDLY_OFFSET];
02786 short data[4000];
02787 };
02788
02789 static void tonepair_release(struct ast_channel *chan, void *params)
02790 {
02791 struct tonepair_state *ts = params;
02792 if (chan) {
02793 ast_set_write_format(chan, ts->origwfmt);
02794 }
02795 free(ts);
02796 }
02797
02798 static void * tonepair_alloc(struct ast_channel *chan, void *params)
02799 {
02800 struct tonepair_state *ts;
02801 struct tonepair_def *td = params;
02802 ts = malloc(sizeof(struct tonepair_state));
02803 if (!ts)
02804 return NULL;
02805 memset(ts, 0, sizeof(struct tonepair_state));
02806 ts->origwfmt = chan->writeformat;
02807 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
02808 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
02809 tonepair_release(NULL, ts);
02810 ts = NULL;
02811 } else {
02812 ts->freq1 = td->freq1;
02813 ts->freq2 = td->freq2;
02814 ts->duration = td->duration;
02815 ts->vol = td->vol;
02816 }
02817
02818 chan->writeinterrupt = 1;
02819 return ts;
02820 }
02821
02822 static int tonepair_generator(struct ast_channel *chan, void *data, int len, int samples)
02823 {
02824 struct tonepair_state *ts = data;
02825 int x;
02826
02827
02828
02829
02830 len = samples * 2;
02831
02832 if (len > sizeof(ts->data) / 2 - 1) {
02833 ast_log(LOG_WARNING, "Can't generate that much data!\n");
02834 return -1;
02835 }
02836 memset(&ts->f, 0, sizeof(ts->f));
02837 for (x=0;x<len/2;x++) {
02838 ts->data[x] = ts->vol * (
02839 sin((ts->freq1 * 2.0 * M_PI / 8000.0) * (ts->pos + x)) +
02840 sin((ts->freq2 * 2.0 * M_PI / 8000.0) * (ts->pos + x))
02841 );
02842 }
02843 ts->f.frametype = AST_FRAME_VOICE;
02844 ts->f.subclass = AST_FORMAT_SLINEAR;
02845 ts->f.datalen = len;
02846 ts->f.samples = samples;
02847 ts->f.offset = AST_FRIENDLY_OFFSET;
02848 ts->f.data = ts->data;
02849 ast_write(chan, &ts->f);
02850 ts->pos += x;
02851 if (ts->duration > 0) {
02852 if (ts->pos >= ts->duration * 8)
02853 return -1;
02854 }
02855 return 0;
02856 }
02857
02858 static struct ast_generator tonepair = {
02859 alloc: tonepair_alloc,
02860 release: tonepair_release,
02861 generate: tonepair_generator,
02862 };
02863
02864 int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
02865 {
02866 struct tonepair_def d = { 0, };
02867 d.freq1 = freq1;
02868 d.freq2 = freq2;
02869 d.duration = duration;
02870 if (vol < 1)
02871 d.vol = 8192;
02872 else
02873 d.vol = vol;
02874 if (ast_activate_generator(chan, &tonepair, &d))
02875 return -1;
02876 return 0;
02877 }
02878
02879 void ast_tonepair_stop(struct ast_channel *chan)
02880 {
02881 ast_deactivate_generator(chan);
02882 }
02883
02884 int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
02885 {
02886 struct ast_frame *f;
02887 int res;
02888 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02889 return res;
02890
02891
02892 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02893 f = ast_read(chan);
02894 if (f)
02895 ast_frfree(f);
02896 else
02897 return -1;
02898 }
02899 return 0;
02900 }
02901
02902 unsigned int ast_get_group(char *s)
02903 {
02904 char *copy;
02905 char *piece;
02906 char *c=NULL;
02907 int start=0, finish=0,x;
02908 unsigned int group = 0;
02909 copy = ast_strdupa(s);
02910 if (!copy) {
02911 ast_log(LOG_ERROR, "Out of memory\n");
02912 return 0;
02913 }
02914 c = copy;
02915
02916 while((piece = strsep(&c, ","))) {
02917 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02918
02919 } else if (sscanf(piece, "%d", &start)) {
02920
02921 finish = start;
02922 } else {
02923 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.\n", s, piece);
02924 continue;
02925 }
02926 for (x=start;x<=finish;x++) {
02927 if ((x > 31) || (x < 0)) {
02928 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02929 } else
02930 group |= (1 << x);
02931 }
02932 }
02933 return group;
02934 }