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 <linux/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 char ast_waitfordigit(struct ast_channel *c, int ms)
01093 {
01094
01095 struct ast_frame *f;
01096 char 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 char 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 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01148 if ((!rchan) && (outfd < 0) && (ms)) {
01149 ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01150 return -1;
01151 } else if (outfd > -1) {
01152
01153 return 1;
01154 } else if (rchan) {
01155 f = ast_read(c);
01156 if(!f) {
01157 return -1;
01158 }
01159
01160 switch(f->frametype) {
01161 case AST_FRAME_DTMF:
01162 res = f->subclass;
01163 ast_frfree(f);
01164 return res;
01165 case AST_FRAME_CONTROL:
01166 switch(f->subclass) {
01167 case AST_CONTROL_HANGUP:
01168 ast_frfree(f);
01169 return -1;
01170 case AST_CONTROL_RINGING:
01171 case AST_CONTROL_ANSWER:
01172
01173 break;
01174 default:
01175 ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", f->subclass);
01176 }
01177 case AST_FRAME_VOICE:
01178
01179 if (audiofd > -1)
01180 write(audiofd, f->data, f->datalen);
01181 }
01182
01183 ast_frfree(f);
01184 }
01185 }
01186 return 0;
01187 }
01188
01189 struct ast_frame *ast_read(struct ast_channel *chan)
01190 {
01191 struct ast_frame *f = NULL;
01192 int blah;
01193 #ifdef ZAPTEL_OPTIMIZATIONS
01194 int (*func)(void *);
01195 void *data;
01196 int res;
01197 #endif
01198 static struct ast_frame null_frame =
01199 {
01200 AST_FRAME_NULL,
01201 };
01202
01203 ast_mutex_lock(&chan->lock);
01204 if (chan->masq) {
01205 if (ast_do_masquerade(chan)) {
01206 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01207 f = NULL;
01208 } else
01209 f = &null_frame;
01210 ast_mutex_unlock(&chan->lock);
01211 return f;
01212 }
01213
01214
01215 if (chan->zombie || ast_check_hangup(chan)) {
01216 if (chan->generator)
01217 ast_deactivate_generator(chan);
01218 ast_mutex_unlock(&chan->lock);
01219 return NULL;
01220 }
01221
01222 if (!chan->deferdtmf && !ast_strlen_zero(chan->dtmfq)) {
01223
01224 chan->dtmff.frametype = AST_FRAME_DTMF;
01225 chan->dtmff.subclass = chan->dtmfq[0];
01226
01227 memmove(chan->dtmfq, chan->dtmfq + 1, sizeof(chan->dtmfq) - 1);
01228 ast_mutex_unlock(&chan->lock);
01229 return &chan->dtmff;
01230 }
01231
01232
01233
01234 if (chan->pvt->alertpipe[0] > -1) {
01235 read(chan->pvt->alertpipe[0], &blah, sizeof(blah));
01236 }
01237 #ifdef ZAPTEL_OPTIMIZATIONS
01238 if ((chan->timingfd > -1) && (chan->fdno == AST_MAX_FDS - 2) && chan->exception) {
01239 chan->exception = 0;
01240 blah = -1;
01241
01242 res = ioctl(chan->timingfd, ZT_GETEVENT, &blah);
01243 if (res)
01244 blah = ZT_EVENT_TIMER_EXPIRED;
01245
01246 if (blah == ZT_EVENT_TIMER_PING) {
01247 #if 0
01248 ast_log(LOG_NOTICE, "Oooh, there's a PING!\n");
01249 #endif
01250 if (!chan->pvt->readq || !chan->pvt->readq->next) {
01251
01252 #if 0
01253 ast_log(LOG_NOTICE, "Sending a PONG!\n");
01254 #endif
01255 if (ioctl(chan->timingfd, ZT_TIMERPONG, &blah)) {
01256 ast_log(LOG_WARNING, "Failed to pong timer on '%s': %s\n", chan->name, strerror(errno));
01257 }
01258 }
01259 } else if (blah == ZT_EVENT_TIMER_EXPIRED) {
01260 ioctl(chan->timingfd, ZT_TIMERACK, &blah);
01261 func = chan->timingfunc;
01262 data = chan->timingdata;
01263 ast_mutex_unlock(&chan->lock);
01264 if (func) {
01265 #if 0
01266 ast_log(LOG_DEBUG, "Calling private function\n");
01267 #endif
01268 func(data);
01269 } else {
01270 blah = 0;
01271 ast_mutex_lock(&chan->lock);
01272 ioctl(chan->timingfd, ZT_TIMERCONFIG, &blah);
01273 chan->timingdata = NULL;
01274 ast_mutex_unlock(&chan->lock);
01275 }
01276 f = &null_frame;
01277 return f;
01278 } else
01279 ast_log(LOG_NOTICE, "No/unknown event '%d' on timer for '%s'?\n", blah, chan->name);
01280 }
01281 #endif
01282
01283 if (chan->pvt->readq) {
01284 f = chan->pvt->readq;
01285 chan->pvt->readq = f->next;
01286
01287 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
01288 ast_frfree(f);
01289 f = NULL;
01290 }
01291 } else {
01292 chan->blocker = pthread_self();
01293 if (chan->exception) {
01294 if (chan->pvt->exception)
01295 f = chan->pvt->exception(chan);
01296 else {
01297 ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
01298 f = &null_frame;
01299 }
01300
01301 chan->exception = 0;
01302 } else
01303 if (chan->pvt->read)
01304 f = chan->pvt->read(chan);
01305 else
01306 ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
01307 }
01308
01309
01310 if (f && (f->frametype == AST_FRAME_VOICE)) {
01311 if (!(f->subclass & chan->nativeformats)) {
01312
01313
01314 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));
01315 ast_frfree(f);
01316 f = &null_frame;
01317 } else {
01318 if (chan->monitor && chan->monitor->read_stream ) {
01319 #ifndef MONITOR_CONSTANT_DELAY
01320 int jump = chan->outsmpl - chan->insmpl - 2 * f->samples;
01321 if (jump >= 0) {
01322 if (ast_seekstream(chan->monitor->read_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01323 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01324 chan->insmpl += jump + 2 * f->samples;
01325 } else
01326 chan->insmpl+= f->samples;
01327 #else
01328 int jump = chan->outsmpl - chan->insmpl;
01329 if (jump - MONITOR_DELAY >= 0) {
01330 if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01331 ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
01332 chan->insmpl += jump;
01333 } else
01334 chan->insmpl += f->samples;
01335 #endif
01336 if (ast_writestream(chan->monitor->read_stream, f) < 0)
01337 ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
01338 }
01339 if (chan->pvt->readtrans) {
01340 f = ast_translate(chan->pvt->readtrans, f, 1);
01341 if (!f)
01342 f = &null_frame;
01343 }
01344 }
01345 }
01346
01347
01348 if (!f) {
01349 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01350 if (chan->generator)
01351 ast_deactivate_generator(chan);
01352
01353 if (chan->cdr)
01354 ast_cdr_end(chan->cdr);
01355 } else if (chan->deferdtmf && f->frametype == AST_FRAME_DTMF) {
01356 if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
01357 chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
01358 else
01359 ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
01360 f = &null_frame;
01361 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
01362 if (chan->_state == AST_STATE_UP) {
01363 ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
01364 f = &null_frame;
01365 }
01366
01367 ast_setstate(chan, AST_STATE_UP);
01368 ast_cdr_answer(chan->cdr);
01369 }
01370
01371
01372 if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
01373
01374
01375 void *tmp;
01376 int res;
01377 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
01378 if (chan->timingfunc) {
01379 ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
01380 ast_settimeout(chan, 0, NULL, NULL);
01381 }
01382 tmp = chan->generatordata;
01383 chan->generatordata = NULL;
01384 generate = chan->generator->generate;
01385 res = generate(chan, tmp, f->datalen, f->samples);
01386 chan->generatordata = tmp;
01387 if (res) {
01388 ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
01389 ast_deactivate_generator(chan);
01390 }
01391 } else if (f && (f->frametype == AST_FRAME_CNG)) {
01392 if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
01393 ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
01394 ast_settimeout(chan, 160, generator_force, chan);
01395 }
01396 }
01397 if (chan->fin & 0x80000000)
01398 ast_frame_dump(chan->name, f, "<<");
01399 if ((chan->fin & 0x7fffffff) == 0x7fffffff)
01400 chan->fin &= 0x80000000;
01401 else
01402 chan->fin++;
01403 ast_mutex_unlock(&chan->lock);
01404 return f;
01405 }
01406
01407 int ast_indicate(struct ast_channel *chan, int condition)
01408 {
01409 int res = -1;
01410
01411 if (chan->zombie || ast_check_hangup(chan))
01412 return -1;
01413 ast_mutex_lock(&chan->lock);
01414 if (chan->pvt->indicate)
01415 res = chan->pvt->indicate(chan, condition);
01416 ast_mutex_unlock(&chan->lock);
01417 if (!chan->pvt->indicate || res) {
01418
01419
01420
01421
01422 if (condition >= 0) {
01423 const struct tone_zone_sound *ts = NULL;
01424 switch (condition) {
01425 case AST_CONTROL_RINGING:
01426 ts = ast_get_indication_tone(chan->zone, "ring");
01427 break;
01428 case AST_CONTROL_BUSY:
01429 ts = ast_get_indication_tone(chan->zone, "busy");
01430 break;
01431 case AST_CONTROL_CONGESTION:
01432 ts = ast_get_indication_tone(chan->zone, "congestion");
01433 break;
01434 }
01435 if (ts && ts->data[0]) {
01436 ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
01437 ast_playtones_start(chan,0,ts->data, 1);
01438 res = 0;
01439 } else if (condition == AST_CONTROL_PROGRESS) {
01440
01441 } else if (condition == AST_CONTROL_PROCEEDING) {
01442
01443 } else {
01444
01445 ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
01446 res = -1;
01447 }
01448 }
01449 else ast_playtones_stop(chan);
01450 }
01451 return res;
01452 }
01453
01454 int ast_recvchar(struct ast_channel *chan, int timeout)
01455 {
01456 int res,ourto,c;
01457 struct ast_frame *f;
01458
01459 ourto = timeout;
01460 for(;;)
01461 {
01462 if (ast_check_hangup(chan)) return -1;
01463 res = ast_waitfor(chan,ourto);
01464 if (res <= 0)
01465 {
01466 return 0;
01467 }
01468 ourto = res;
01469 f = ast_read(chan);
01470 if (f == NULL) return -1;
01471 if ((f->frametype == AST_FRAME_CONTROL) &&
01472 (f->subclass == AST_CONTROL_HANGUP)) return -1;
01473 if (f->frametype == AST_FRAME_TEXT)
01474 {
01475 c = *((char *)f->data);
01476 ast_frfree(f);
01477 return(c);
01478 }
01479 ast_frfree(f);
01480 }
01481 }
01482
01483 int ast_sendtext(struct ast_channel *chan, char *text)
01484 {
01485 int res = 0;
01486
01487 if (chan->zombie || ast_check_hangup(chan))
01488 return -1;
01489 CHECK_BLOCKING(chan);
01490 if (chan->pvt->send_text)
01491 res = chan->pvt->send_text(chan, text);
01492 chan->blocking = 0;
01493 return res;
01494 }
01495
01496 static int do_senddigit(struct ast_channel *chan, char digit)
01497 {
01498 int res = -1;
01499
01500 if (chan->pvt->send_digit)
01501 res = chan->pvt->send_digit(chan, digit);
01502 if (!chan->pvt->send_digit || res) {
01503
01504
01505
01506
01507 static const char* dtmf_tones[] = {
01508 "!941+1336/100,!0/100",
01509 "!697+1209/100,!0/100",
01510 "!697+1336/100,!0/100",
01511 "!697+1477/100,!0/100",
01512 "!770+1209/100,!0/100",
01513 "!770+1336/100,!0/100",
01514 "!770+1477/100,!0/100",
01515 "!852+1209/100,!0/100",
01516 "!852+1336/100,!0/100",
01517 "!852+1477/100,!0/100",
01518 "!697+1633/100,!0/100",
01519 "!770+1633/100,!0/100",
01520 "!852+1633/100,!0/100",
01521 "!941+1633/100,!0/100",
01522 "!941+1209/100,!0/100",
01523 "!941+1477/100,!0/100" };
01524 if (digit >= '0' && digit <='9')
01525 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
01526 else if (digit >= 'A' && digit <= 'D')
01527 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
01528 else if (digit == '*')
01529 ast_playtones_start(chan,0,dtmf_tones[14], 0);
01530 else if (digit == '#')
01531 ast_playtones_start(chan,0,dtmf_tones[15], 0);
01532 else {
01533
01534 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
01535 }
01536 }
01537 return 0;
01538 }
01539
01540 int ast_senddigit(struct ast_channel *chan, char digit)
01541 {
01542 return do_senddigit(chan, digit);
01543 }
01544
01545 int ast_prod(struct ast_channel *chan)
01546 {
01547 struct ast_frame a = { AST_FRAME_VOICE };
01548 char nothing[128];
01549
01550 if (chan->_state != AST_STATE_UP) {
01551 ast_log(LOG_DEBUG, "Prodding channel '%s'\n", chan->name);
01552 a.subclass = chan->pvt->rawwriteformat;
01553 a.data = nothing + AST_FRIENDLY_OFFSET;
01554 if (ast_write(chan, &a))
01555 ast_log(LOG_WARNING, "Prodding channel '%s' failed\n", chan->name);
01556 }
01557 return 0;
01558 }
01559
01560 int ast_write_video(struct ast_channel *chan, struct ast_frame *fr)
01561 {
01562 int res;
01563 if (!chan->pvt->write_video)
01564 return 0;
01565 res = ast_write(chan, fr);
01566 if (!res)
01567 res = 1;
01568 return res;
01569 }
01570
01571 int ast_write(struct ast_channel *chan, struct ast_frame *fr)
01572 {
01573 int res = -1;
01574 struct ast_frame *f = NULL;
01575
01576 ast_mutex_lock(&chan->lock);
01577 if (chan->zombie || ast_check_hangup(chan)) {
01578 ast_mutex_unlock(&chan->lock);
01579 return -1;
01580 }
01581
01582 if (chan->masq) {
01583 if (ast_do_masquerade(chan)) {
01584 ast_log(LOG_WARNING, "Failed to perform masquerade\n");
01585 ast_mutex_unlock(&chan->lock);
01586 return -1;
01587 }
01588 }
01589 if (chan->masqr) {
01590 ast_mutex_unlock(&chan->lock);
01591 return 0;
01592 }
01593 if (chan->generatordata) {
01594 if (chan->writeinterrupt)
01595 ast_deactivate_generator(chan);
01596 else {
01597 ast_mutex_unlock(&chan->lock);
01598 return 0;
01599 }
01600 }
01601 if (chan->fout & 0x80000000)
01602 ast_frame_dump(chan->name, fr, ">>");
01603 CHECK_BLOCKING(chan);
01604 switch(fr->frametype) {
01605 case AST_FRAME_CONTROL:
01606
01607 ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
01608 break;
01609 case AST_FRAME_DTMF:
01610 chan->blocking = 0;
01611 ast_mutex_unlock(&chan->lock);
01612 res = do_senddigit(chan,fr->subclass);
01613 ast_mutex_lock(&chan->lock);
01614 CHECK_BLOCKING(chan);
01615 break;
01616 case AST_FRAME_TEXT:
01617 if (chan->pvt->send_text)
01618 res = chan->pvt->send_text(chan, (char *) fr->data);
01619 break;
01620 case AST_FRAME_VIDEO:
01621
01622 if (chan->pvt->write_video)
01623 res = chan->pvt->write_video(chan, fr);
01624 else
01625 res = 0;
01626 break;
01627 default:
01628 if (chan->pvt->write) {
01629 if (chan->pvt->writetrans) {
01630 f = ast_translate(chan->pvt->writetrans, fr, 0);
01631 } else
01632 f = fr;
01633 if (f) {
01634 res = chan->pvt->write(chan, f);
01635 if( chan->monitor &&
01636 chan->monitor->write_stream &&
01637 f && ( f->frametype == AST_FRAME_VOICE ) ) {
01638 #ifndef MONITOR_CONSTANT_DELAY
01639 int jump = chan->insmpl - chan->outsmpl - 2 * f->samples;
01640 if (jump >= 0) {
01641 if (ast_seekstream(chan->monitor->write_stream, jump + f->samples, SEEK_FORCECUR) == -1)
01642 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01643 chan->outsmpl += jump + 2 * f->samples;
01644 } else
01645 chan->outsmpl += f->samples;
01646 #else
01647 int jump = chan->insmpl - chan->outsmpl;
01648 if (jump - MONITOR_DELAY >= 0) {
01649 if (ast_seekstream(chan->monitor->write_stream, jump - f->samples, SEEK_FORCECUR) == -1)
01650 ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
01651 chan->outsmpl += jump;
01652 } else
01653 chan->outsmpl += f->samples;
01654 #endif
01655 if (ast_writestream(chan->monitor->write_stream, f) < 0)
01656 ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
01657 }
01658 } else
01659 res = 0;
01660 }
01661 }
01662 if (f && (f != fr))
01663 ast_frfree(f);
01664 chan->blocking = 0;
01665
01666 if (res < 0)
01667 chan->_softhangup |= AST_SOFTHANGUP_DEV;
01668 else {
01669 if ((chan->fout & 0x7fffffff) == 0x7fffffff)
01670 chan->fout &= 0x80000000;
01671 else
01672 chan->fout++;
01673 chan->fout++;
01674 }
01675 ast_mutex_unlock(&chan->lock);
01676 return res;
01677 }
01678
01679 int ast_set_write_format(struct ast_channel *chan, int fmts)
01680 {
01681 int fmt;
01682 int native;
01683 int res;
01684
01685 ast_mutex_lock(&chan->lock);
01686 native = chan->nativeformats;
01687 fmt = fmts;
01688
01689 res = ast_translator_best_choice(&native, &fmt);
01690 if (res < 0) {
01691 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01692 ast_getformatname(fmts), ast_getformatname(chan->nativeformats));
01693 ast_mutex_unlock(&chan->lock);
01694 return -1;
01695 }
01696
01697
01698 chan->pvt->rawwriteformat = native;
01699
01700 chan->writeformat = fmt;
01701
01702 if (chan->pvt->writetrans)
01703 ast_translator_free_path(chan->pvt->writetrans);
01704
01705 chan->pvt->writetrans = ast_translator_build_path(chan->pvt->rawwriteformat, chan->writeformat);
01706 if (option_debug)
01707 ast_log(LOG_DEBUG, "Set channel %s to write format %s\n", chan->name, ast_getformatname(chan->writeformat));
01708 ast_mutex_unlock(&chan->lock);
01709 return 0;
01710 }
01711
01712 int ast_set_read_format(struct ast_channel *chan, int fmts)
01713 {
01714 int fmt;
01715 int native;
01716 int res;
01717
01718 ast_mutex_lock(&chan->lock);
01719 native = chan->nativeformats;
01720 fmt = fmts;
01721
01722 res = ast_translator_best_choice(&fmt, &native);
01723 if (res < 0) {
01724 ast_log(LOG_NOTICE, "Unable to find a path from %s to %s\n",
01725 ast_getformatname(chan->nativeformats), ast_getformatname(fmts));
01726 ast_mutex_unlock(&chan->lock);
01727 return -1;
01728 }
01729
01730
01731 chan->pvt->rawreadformat = native;
01732
01733 chan->readformat = fmt;
01734
01735 if (chan->pvt->readtrans)
01736 ast_translator_free_path(chan->pvt->readtrans);
01737
01738 chan->pvt->readtrans = ast_translator_build_path(chan->readformat, chan->pvt->rawreadformat);
01739 if (option_debug)
01740 ast_log(LOG_DEBUG, "Set channel %s to read format %s\n",
01741 chan->name, ast_getformatname(chan->readformat));
01742 ast_mutex_unlock(&chan->lock);
01743 return 0;
01744 }
01745
01746 struct ast_channel *__ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, char *callerid, struct outgoing_helper *oh)
01747 {
01748 int state = 0;
01749 struct ast_channel *chan;
01750 struct ast_frame *f;
01751 int res = 0;
01752 char *variable;
01753 chan = ast_request(type, format, data);
01754 if (chan) {
01755 if (oh) {
01756 char *tmp, *var;
01757
01758 if (oh->variable)
01759 variable = ast_strdupa(oh->variable);
01760 else
01761 variable = NULL;
01762 tmp = variable;
01763
01764 while( (var = strtok_r(NULL, "|", &tmp)) ) {
01765 pbx_builtin_setvar( chan, var );
01766 }
01767 if (oh->callerid && *oh->callerid)
01768 ast_set_callerid(chan, oh->callerid, 1);
01769 if (oh->account && *oh->account)
01770 ast_cdr_setaccount(chan, oh->account);
01771 }
01772 if (callerid && !ast_strlen_zero(callerid))
01773 ast_set_callerid(chan, callerid, 1);
01774
01775 if (!ast_call(chan, data, 0)) {
01776 while(timeout && (chan->_state != AST_STATE_UP)) {
01777 res = ast_waitfor(chan, timeout);
01778 if (res < 0) {
01779
01780 break;
01781 }
01782
01783 if (!res)
01784 break;
01785 if (timeout > -1)
01786 timeout = res;
01787 f = ast_read(chan);
01788 if (!f) {
01789 state = AST_CONTROL_HANGUP;
01790 res = 0;
01791 break;
01792 }
01793 if (f->frametype == AST_FRAME_CONTROL) {
01794 if (f->subclass == AST_CONTROL_RINGING)
01795 state = AST_CONTROL_RINGING;
01796 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
01797 state = f->subclass;
01798 ast_frfree(f);
01799 break;
01800 } else if (f->subclass == AST_CONTROL_ANSWER) {
01801 state = f->subclass;
01802 ast_frfree(f);
01803 break;
01804 } else if (f->subclass == AST_CONTROL_PROGRESS) {
01805
01806 } else if (f->subclass == -1) {
01807
01808 } else {
01809 ast_log(LOG_NOTICE, "Don't know what to do with control frame %d\n", f->subclass);
01810 }
01811 }
01812 ast_frfree(f);
01813 }
01814 } else
01815 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01816 } else
01817 ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
01818 if (chan) {
01819
01820 if (oh) {
01821 if (oh->context && *oh->context)
01822 strncpy(chan->context, oh->context, sizeof(chan->context) - 1);
01823 if (oh->exten && *oh->exten)
01824 strncpy(chan->exten, oh->exten, sizeof(chan->exten) - 1);
01825 chan->priority = oh->priority;
01826 }
01827 if (chan->_state == AST_STATE_UP)
01828 state = AST_CONTROL_ANSWER;
01829 }
01830 if (outstate)
01831 *outstate = state;
01832 if (chan && res <= 0) {
01833 if (!chan->cdr) {
01834 chan->cdr = ast_cdr_alloc();
01835 if (chan->cdr)
01836 ast_cdr_init(chan->cdr, chan);
01837 }
01838 if (chan->cdr) {
01839 char tmp[256];
01840 snprintf(tmp, 256, "%s/%s", type, (char *)data);
01841 ast_cdr_setapp(chan->cdr,"Dial",tmp);
01842 ast_cdr_update(chan);
01843 ast_cdr_start(chan->cdr);
01844 ast_cdr_end(chan->cdr);
01845
01846 if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
01847 ast_cdr_failed(chan->cdr);
01848 } else
01849 ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
01850 ast_hangup(chan);
01851 chan = NULL;
01852 }
01853 return chan;
01854 }
01855
01856 struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, char *callerid)
01857 {
01858 return __ast_request_and_dial(type, format, data, timeout, outstate, callerid, NULL);
01859 }
01860
01861 struct ast_channel *ast_request(char *type, int format, void *data)
01862 {
01863 struct chanlist *chan;
01864 struct ast_channel *c = NULL;
01865 int capabilities;
01866 int fmt;
01867 int res;
01868 if (ast_mutex_lock(&chlock)) {
01869 ast_log(LOG_WARNING, "Unable to lock channel list\n");
01870 return NULL;
01871 }
01872 chan = backends;
01873 while(chan) {
01874 if (!strcasecmp(type, chan->type)) {
01875 capabilities = chan->capabilities;
01876 fmt = format;
01877 res = ast_translator_best_choice(&fmt, &capabilities);
01878 if (res < 0) {
01879 ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %d) to %d\n", type, chan->capabilities, format);
01880 ast_mutex_unlock(&chlock);
01881 return NULL;
01882 }
01883 ast_mutex_unlock(&chlock);
01884 if (chan->requester)
01885 c = chan->requester(type, capabilities, data);
01886 if (c) {
01887 if (c->_state == AST_STATE_DOWN) {
01888 manager_event(EVENT_FLAG_CALL, "Newchannel",
01889 "Channel: %s\r\n"
01890 "State: %s\r\n"
01891 "Callerid: %s\r\n"
01892 "Uniqueid: %s\r\n",
01893 c->name, ast_state2str(c->_state), c->callerid ? c->callerid : "<unknown>", c->uniqueid);
01894 }
01895 }
01896 return c;
01897 }
01898 chan = chan->next;
01899 }
01900 if (!chan)
01901 ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
01902 ast_mutex_unlock(&chlock);
01903 return c;
01904 }
01905
01906 int ast_parse_device_state(char *device)
01907 {
01908 char name[AST_CHANNEL_NAME] = "";
01909 char *cut;
01910 struct ast_channel *chan;
01911
01912 chan = ast_channel_walk_locked(NULL);
01913 while (chan) {
01914 strncpy(name, chan->name, sizeof(name)-1);
01915 ast_mutex_unlock(&chan->lock);
01916 cut = strchr(name,'-');
01917 if (cut)
01918 *cut = 0;
01919 if (!strcmp(name, device))
01920 return AST_DEVICE_INUSE;
01921 chan = ast_channel_walk_locked(chan);
01922 }
01923 return AST_DEVICE_UNKNOWN;
01924 }
01925
01926 int ast_device_state(char *device)
01927 {
01928 char tech[AST_MAX_EXTENSION] = "";
01929 char *number;
01930 struct chanlist *chanls;
01931 int res = 0;
01932
01933 strncpy(tech, device, sizeof(tech)-1);
01934 number = strchr(tech, '/');
01935 if (!number) {
01936 return AST_DEVICE_INVALID;
01937 }
01938 *number = 0;
01939 number++;
01940
01941 if (ast_mutex_lock(&chlock)) {
01942 ast_log(LOG_WARNING, "Unable to lock channel list\n");
01943 return -1;
01944 }
01945 chanls = backends;
01946 while(chanls) {
01947 if (!strcasecmp(tech, chanls->type)) {
01948 ast_mutex_unlock(&chlock);
01949 if (!chanls->devicestate)
01950 return ast_parse_device_state(device);
01951 else {
01952 res = chanls->devicestate(number);
01953 if (res == AST_DEVICE_UNKNOWN)
01954 return ast_parse_device_state(device);
01955 else
01956 return res;
01957 }
01958 }
01959 chanls = chanls->next;
01960 }
01961 ast_mutex_unlock(&chlock);
01962 return AST_DEVICE_INVALID;
01963 }
01964
01965 int ast_call(struct ast_channel *chan, char *addr, int timeout)
01966 {
01967
01968
01969
01970 int res = -1;
01971
01972 ast_mutex_lock(&chan->lock);
01973 if (!chan->zombie && !ast_check_hangup(chan))
01974 if (chan->pvt->call)
01975 res = chan->pvt->call(chan, addr, timeout);
01976 ast_mutex_unlock(&chan->lock);
01977 return res;
01978 }
01979
01980 int ast_transfer(struct ast_channel *chan, char *dest)
01981 {
01982
01983
01984
01985 int res = -1;
01986
01987 ast_mutex_lock(&chan->lock);
01988 if (!chan->zombie && !ast_check_hangup(chan)) {
01989 if (chan->pvt->transfer) {
01990 res = chan->pvt->transfer(chan, dest);
01991 if (!res)
01992 res = 1;
01993 } else
01994 res = 0;
01995 }
01996 ast_mutex_unlock(&chan->lock);
01997 return res;
01998 }
01999
02000 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
02001 {
02002 int pos=0;
02003 int to = ftimeout;
02004 char d;
02005
02006
02007 if (c->zombie || ast_check_hangup(c))
02008 return -1;
02009 if (!len)
02010 return -1;
02011 do {
02012 if (c->stream) {
02013 d = ast_waitstream(c, AST_DIGIT_ANY);
02014 ast_stopstream(c);
02015 usleep(1000);
02016 if (!d)
02017 d = ast_waitfordigit(c, to);
02018 } else {
02019 d = ast_waitfordigit(c, to);
02020 }
02021 if (d < 0)
02022 return -1;
02023 if (d == 0) {
02024 s[pos]='\0';
02025 return 1;
02026 }
02027 if (!strchr(enders, d))
02028 s[pos++] = d;
02029 if (strchr(enders, d) || (pos >= len)) {
02030 s[pos]='\0';
02031 return 0;
02032 }
02033 to = timeout;
02034 } while(1);
02035
02036 return 0;
02037 }
02038
02039 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
02040 {
02041 int pos=0;
02042 int to = ftimeout;
02043 char d;
02044
02045 if (c->zombie || ast_check_hangup(c))
02046 return -1;
02047 if (!len)
02048 return -1;
02049 do {
02050 if (c->stream) {
02051 d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
02052 ast_stopstream(c);
02053 usleep(1000);
02054 if (!d)
02055 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02056 } else {
02057 d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
02058 }
02059 if (d < 0)
02060 return -1;
02061 if (d == 0) {
02062 s[pos]='\0';
02063 return 1;
02064 }
02065 if (d == 1) {
02066 s[pos]='\0';
02067 return 2;
02068 }
02069 if (!strchr(enders, d))
02070 s[pos++] = d;
02071 if (strchr(enders, d) || (pos >= len)) {
02072 s[pos]='\0';
02073 return 0;
02074 }
02075 to = timeout;
02076 } while(1);
02077
02078 return 0;
02079 }
02080
02081 int ast_channel_supports_html(struct ast_channel *chan)
02082 {
02083 if (chan->pvt->send_html)
02084 return 1;
02085 return 0;
02086 }
02087
02088 int ast_channel_sendhtml(struct ast_channel *chan, int subclass, char *data, int datalen)
02089 {
02090 if (chan->pvt->send_html)
02091 return chan->pvt->send_html(chan, subclass, data, datalen);
02092 return -1;
02093 }
02094
02095 int ast_channel_sendurl(struct ast_channel *chan, char *url)
02096 {
02097 if (chan->pvt->send_html)
02098 return chan->pvt->send_html(chan, AST_HTML_URL, url, strlen(url) + 1);
02099 return -1;
02100 }
02101
02102 int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
02103 {
02104 int peerf;
02105 int chanf;
02106 int res;
02107 ast_mutex_lock(&peer->lock);
02108 peerf = peer->nativeformats;
02109 ast_mutex_unlock(&peer->lock);
02110 ast_mutex_lock(&chan->lock);
02111 chanf = chan->nativeformats;
02112 ast_mutex_unlock(&chan->lock);
02113 res = ast_translator_best_choice(&peerf, &chanf);
02114 if (res < 0) {
02115 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", chan->name, chan->nativeformats, peer->name, peer->nativeformats);
02116 return -1;
02117 }
02118
02119 res = ast_set_read_format(chan, peerf);
02120 if (res < 0) {
02121 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", chan->name, chanf);
02122 return -1;
02123 }
02124
02125 res = ast_set_write_format(peer, peerf);
02126 if (res < 0) {
02127 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", peer->name, peerf);
02128 return -1;
02129 }
02130
02131 peerf = peer->nativeformats;
02132 chanf = chan->nativeformats;
02133 res = ast_translator_best_choice(&chanf, &peerf);
02134 if (res < 0) {
02135 ast_log(LOG_WARNING, "No path to translate from %s(%d) to %s(%d)\n", peer->name, peer->nativeformats, chan->name, chan->nativeformats);
02136 return -1;
02137 }
02138
02139 res = ast_set_write_format(chan, chanf);
02140 if (res < 0) {
02141 ast_log(LOG_WARNING, "Unable to set write format on channel %s to %d\n", chan->name, chanf);
02142 return -1;
02143 }
02144
02145 res = ast_set_read_format(peer, chanf);
02146 if (res < 0) {
02147 ast_log(LOG_WARNING, "Unable to set read format on channel %s to %d\n", peer->name, peerf);
02148 return -1;
02149 }
02150 return 0;
02151 }
02152
02153 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
02154 {
02155 struct ast_frame null = { AST_FRAME_NULL, };
02156 int res = -1;
02157 ast_mutex_lock(&original->lock);
02158 while(ast_mutex_trylock(&clone->lock)) {
02159 ast_mutex_unlock(&original->lock);
02160 usleep(1);
02161 ast_mutex_lock(&original->lock);
02162 }
02163 ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
02164 clone->name, original->name);
02165 if (original->masq) {
02166 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
02167 original->masq->name, original->name);
02168 } else if (clone->masqr) {
02169 ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
02170 clone->name, clone->masqr->name);
02171 } else {
02172 original->masq = clone;
02173 clone->masqr = original;
02174 ast_queue_frame(original, &null);
02175 ast_queue_frame(clone, &null);
02176 ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
02177 res = 0;
02178 }
02179 ast_mutex_unlock(&clone->lock);
02180 ast_mutex_unlock(&original->lock);
02181 return res;
02182 }
02183
02184 void ast_change_name(struct ast_channel *chan, char *newname)
02185 {
02186 char tmp[256];
02187 strncpy(tmp, chan->name, sizeof(tmp) - 1);
02188 strncpy(chan->name, newname, sizeof(chan->name) - 1);
02189 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", tmp, chan->name, chan->uniqueid);
02190 }
02191
02192 int ast_do_masquerade(struct ast_channel *original)
02193 {
02194 int x,i;
02195 int res=0;
02196 int origstate;
02197 char *tmp;
02198 struct ast_var_t *varptr;
02199 struct ast_frame *cur, *prev;
02200 struct ast_channel_pvt *p;
02201 struct ast_channel *clone = original->masq;
02202 int rformat = original->readformat;
02203 int wformat = original->writeformat;
02204 char newn[100];
02205 char orig[100];
02206 char masqn[100];
02207 char zombn[100];
02208
02209 #if 1
02210 ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
02211 clone->name, clone->_state, original->name, original->_state);
02212 #endif
02213
02214
02215
02216
02217
02218
02219 ast_mutex_lock(&clone->lock);
02220
02221 ast_log(LOG_DEBUG, "Got clone lock on '%s' at %p\n", clone->name, &clone->lock);
02222
02223
02224
02225 free_translation(clone);
02226 free_translation(original);
02227
02228
02229
02230 original->masq = NULL;
02231 clone->masqr = NULL;
02232
02233
02234 strncpy(orig, original->name, sizeof(orig) - 1);
02235
02236 strncpy(newn, clone->name, sizeof(newn) - 1);
02237
02238 snprintf(masqn, sizeof(masqn), "%s<MASQ>", newn);
02239
02240
02241 strncpy(original->name, newn, sizeof(original->name)-1);
02242
02243
02244 strncpy(clone->name, masqn, sizeof(clone->name) - 1);
02245
02246
02247 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
02248 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
02249
02250
02251 p = original->pvt;
02252 original->pvt = clone->pvt;
02253 clone->pvt = p;
02254
02255
02256
02257 prev = NULL;
02258 cur = clone->pvt->readq;
02259 x = 0;
02260 while(cur) {
02261 x++;
02262 prev = cur;
02263 cur = cur->next;
02264 }
02265
02266
02267 if (prev) {
02268 prev->next = original->pvt->readq;
02269 original->pvt->readq = clone->pvt->readq;
02270 clone->pvt->readq = NULL;
02271 if (original->pvt->alertpipe[1] > -1) {
02272 for (i=0;i<x;i++)
02273 write(original->pvt->alertpipe[1], &x, sizeof(x));
02274 }
02275 }
02276 clone->_softhangup = AST_SOFTHANGUP_DEV;
02277
02278
02279
02280
02281
02282
02283 origstate = original->_state;
02284 original->_state = clone->_state;
02285 clone->_state = origstate;
02286
02287 if (clone->pvt->fixup){
02288 res = clone->pvt->fixup(original, clone);
02289 if (res)
02290 ast_log(LOG_WARNING, "Fixup failed on channel %s, strange things may happen.\n", clone->name);
02291 }
02292
02293
02294 if (clone->pvt->hangup)
02295 res = clone->pvt->hangup(clone);
02296 if (res) {
02297 ast_log(LOG_WARNING, "Hangup failed! Strange things may happen!\n");
02298 ast_mutex_unlock(&clone->lock);
02299 return -1;
02300 }
02301
02302 snprintf(zombn, sizeof(zombn), "%s<ZOMBIE>", orig);
02303
02304 strncpy(clone->name, zombn, sizeof(clone->name) - 1);
02305 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", masqn, zombn, clone->uniqueid);
02306
02307
02308
02309 original->type = clone->type;
02310
02311 for (x=0;x<AST_MAX_FDS;x++) {
02312 original->fds[x] = clone->fds[x];
02313 }
02314
02315
02316 varptr = original->varshead.first;
02317 if (varptr) {
02318 while(varptr->entries.next) {
02319 varptr = varptr->entries.next;
02320 }
02321 varptr->entries.next = clone->varshead.first;
02322 } else {
02323 original->varshead.first = clone->varshead.first;
02324 }
02325 clone->varshead.first = NULL;
02326
02327 original->adsicpe = clone->adsicpe;
02328
02329
02330
02331
02332
02333 original->exception = clone->exception;
02334 original->fdno = clone->fdno;
02335
02336
02337
02338
02339
02340
02341
02342 tmp = original->dnid;
02343 original->dnid = clone->dnid;
02344 clone->dnid = tmp;
02345
02346 tmp = original->callerid;
02347 original->callerid = clone->callerid;
02348 clone->callerid = tmp;
02349
02350
02351 original->fds[AST_MAX_FDS - 2] = original->timingfd;
02352
02353
02354 original->nativeformats = clone->nativeformats;
02355
02356
02357
02358
02359
02360 ast_set_write_format(original, wformat);
02361
02362
02363 ast_set_read_format(original, rformat);
02364
02365 ast_log(LOG_DEBUG, "Putting channel %s in %d/%d formats\n", original->name, wformat, rformat);
02366
02367
02368
02369 if (original->pvt->fixup) {
02370 res = original->pvt->fixup(clone, original);
02371 if (res) {
02372 ast_log(LOG_WARNING, "Driver for '%s' could not fixup channel %s\n",
02373 original->type, original->name);
02374 ast_mutex_unlock(&clone->lock);
02375 return -1;
02376 }
02377 } else
02378 ast_log(LOG_WARNING, "Driver '%s' does not have a fixup routine (for %s)! Bad things may happen.\n",
02379 original->type, original->name);
02380
02381
02382
02383
02384 if (clone->zombie) {
02385 ast_log(LOG_DEBUG, "Destroying clone '%s'\n", clone->name);
02386 ast_mutex_unlock(&clone->lock);
02387 ast_channel_free(clone);
02388 manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
02389 } else {
02390 ast_log(LOG_DEBUG, "Released clone lock on '%s'\n", clone->name);
02391 clone->zombie=1;
02392 ast_mutex_unlock(&clone->lock);
02393 }
02394
02395
02396 if (original->blocking)
02397 pthread_kill(original->blocker, SIGURG);
02398 ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n",
02399 original->name, original->_state);
02400 return 0;
02401 }
02402
02403 void ast_set_callerid(struct ast_channel *chan, char *callerid, int anitoo)
02404 {
02405 if (chan->callerid)
02406 free(chan->callerid);
02407 if (anitoo && chan->ani)
02408 free(chan->ani);
02409 if (callerid) {
02410 chan->callerid = strdup(callerid);
02411 if (anitoo)
02412 chan->ani = strdup(callerid);
02413 } else {
02414 chan->callerid = NULL;
02415 if (anitoo)
02416 chan->ani = NULL;
02417 }
02418 if (chan->cdr)
02419 ast_cdr_setcid(chan->cdr, chan);
02420 manager_event(EVENT_FLAG_CALL, "Newcallerid",
02421 "Channel: %s\r\n"
02422 "Callerid: %s\r\n"
02423 "Uniqueid: %s\r\n",
02424 chan->name, chan->callerid ?
02425 chan->callerid : "<Unknown>",
02426 chan->uniqueid);
02427 }
02428
02429 int ast_setstate(struct ast_channel *chan, int state)
02430 {
02431 if (chan->_state != state) {
02432 int oldstate = chan->_state;
02433 chan->_state = state;
02434 if (oldstate == AST_STATE_DOWN) {
02435 ast_device_state_changed(chan->name);
02436 manager_event(EVENT_FLAG_CALL, "Newchannel",
02437 "Channel: %s\r\n"
02438 "State: %s\r\n"
02439 "Callerid: %s\r\n"
02440 "Uniqueid: %s\r\n",
02441 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02442 } else {
02443 manager_event(EVENT_FLAG_CALL, "Newstate",
02444 "Channel: %s\r\n"
02445 "State: %s\r\n"
02446 "Callerid: %s\r\n"
02447 "Uniqueid: %s\r\n",
02448 chan->name, ast_state2str(chan->_state), chan->callerid ? chan->callerid : "<unknown>", chan->uniqueid);
02449 }
02450 }
02451 return 0;
02452 }
02453
02454 static long tvdiff(struct timeval *now, struct timeval *then)
02455 {
02456 return (((now->tv_sec * 1000) + now->tv_usec / 1000) - ((then->tv_sec * 1000) + then->tv_usec / 1000));
02457 }
02458
02459 static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer, char *sound, int remain)
02460 {
02461 int res=0, min=0, sec=0,check=0;
02462
02463 check = ast_autoservice_start(peer);
02464 if(check)
02465 return;
02466
02467 if (remain > 0) {
02468 if (remain / 60 > 1) {
02469 min = remain / 60;
02470 sec = remain % 60;
02471 } else {
02472 sec = remain;
02473 }
02474 }
02475
02476 if (!strcmp(sound,"timeleft")) {
02477 res = ast_streamfile(chan, "vm-youhave", chan->language);
02478 res = ast_waitstream(chan, "");
02479 if (min) {
02480 res = ast_say_number(chan, min, AST_DIGIT_ANY, chan->language, (char *) NULL);
02481 res = ast_streamfile(chan, "queue-minutes", chan->language);
02482 res = ast_waitstream(chan, "");
02483 }
02484 if (sec) {
02485 res = ast_say_number(chan, sec, AST_DIGIT_ANY, chan->language, (char *) NULL);
02486 res = ast_streamfile(chan, "queue-seconds", chan->language);
02487 res = ast_waitstream(chan, "");
02488 }
02489 } else {
02490 res = ast_streamfile(chan, sound, chan->language);
02491 res = ast_waitstream(chan, "");
02492 }
02493
02494 check = ast_autoservice_stop(peer);
02495 }
02496
02497 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)
02498 {
02499
02500
02501 int flags;
02502 struct ast_channel *cs[3];
02503 int to = -1;
02504 struct ast_frame *f;
02505 struct ast_channel *who = NULL;
02506 int res=0;
02507 int nativefailed=0;
02508 int firstpass;
02509 int o0nativeformats;
02510 int o1nativeformats;
02511 struct timeval start_time,precise_now;
02512 long elapsed_ms=0, time_left_ms=0;
02513 int playit=0, playitagain=1, first_time=1;
02514
02515 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);
02516
02517 firstpass = config->firstpass;
02518 config->firstpass = 0;
02519
02520
02521 gettimeofday(&start_time,NULL);
02522 time_left_ms = config->timelimit;
02523
02524 if (config->play_to_caller && config->start_sound && firstpass)
02525 bridge_playfile(c0,c1,config->start_sound,time_left_ms / 1000);
02526 if (config->play_to_callee && config->start_sound && firstpass)
02527 bridge_playfile(c1,c0,config->start_sound,time_left_ms / 1000);
02528
02529
02530 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1))
02531 return -1;
02532 if (c0->bridge) {
02533 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
02534 c0->name, c0->bridge->name);
02535 return -1;
02536 }
02537 if (c1->bridge) {
02538 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
02539 c1->name, c1->bridge->name);
02540 return -1;
02541 }
02542
02543
02544 c0->bridge = c1;
02545 c1->bridge = c0;
02546 cs[0] = c0;
02547 cs[1] = c1;
02548
02549 manager_event(EVENT_FLAG_CALL, "Link",
02550 "Channel1: %s\r\n"
02551 "Channel2: %s\r\n"
02552 "Uniqueid1: %s\r\n"
02553 "Uniqueid2: %s\r\n",
02554 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02555 o1nativeformats = c1->nativeformats;
02556 o0nativeformats = c0->nativeformats;
02557 for (;;) {
02558
02559 if (config->timelimit) {
02560 gettimeofday(&precise_now,NULL);
02561 elapsed_ms = tvdiff(&precise_now,&start_time);
02562 time_left_ms = config->timelimit - elapsed_ms;
02563
02564 if (playitagain && (config->play_to_caller || config->play_to_callee) && (config->play_warning && time_left_ms <= config->play_warning)) {
02565
02566 if (config->warning_freq == 0) {
02567 playit = 1;
02568 first_time=0;
02569 playitagain=0;
02570 } else if (first_time) {
02571 playit = 1;
02572 first_time=0;
02573 } else {
02574 if ((time_left_ms % config->warning_freq) <= 50) {
02575 playit = 1;
02576 }
02577 }
02578 }
02579 if (time_left_ms <= 0) {
02580 if (config->play_to_caller && config->end_sound)
02581 bridge_playfile(c0,c1,config->end_sound,0);
02582 if (config->play_to_callee && config->end_sound)
02583 bridge_playfile(c1,c0,config->end_sound,0);
02584 *fo = NULL;
02585 if (who) *rc = who;
02586 res = 0;
02587 break;
02588 }
02589 if (time_left_ms >= 5000 && playit) {
02590 if (config->play_to_caller && config->warning_sound && config->play_warning)
02591 bridge_playfile(c0,c1,config->warning_sound,time_left_ms / 1000);
02592 if (config->play_to_callee && config->warning_sound && config->play_warning)
02593 bridge_playfile(c1,c0,config->warning_sound,time_left_ms / 1000);
02594 playit = 0;
02595 }
02596
02597 }
02598
02599 if (c0->zombie || ast_check_hangup_locked(c0) || c1->zombie || ast_check_hangup_locked(c1)) {
02600 *fo = NULL;
02601 if (who) *rc = who;
02602 res = 0;
02603 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");
02604 break;
02605 }
02606 if (c0->pvt->bridge && config->timelimit==0 &&
02607 (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
02608
02609 if (option_verbose > 2)
02610 ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
02611 if (!(res = c0->pvt->bridge(c0, c1, flags, fo, rc))) {
02612 c0->bridge = NULL;
02613 c1->bridge = NULL;
02614 manager_event(EVENT_FLAG_CALL, "Unlink",
02615 "Channel1: %s\r\n"
02616 "Channel2: %s\r\n"
02617 "Uniqueid1: %s\r\n"
02618 "Uniqueid2: %s\r\n",
02619 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02620 ast_log(LOG_DEBUG, "Returning from native bridge, channels: %s, %s\n",c0->name ,c1->name);
02621 return 0;
02622 }
02623
02624
02625 if ((res != -2) && (res != -3))
02626 ast_log(LOG_WARNING, "Private bridge between %s and %s failed\n", c0->name, c1->name);
02627 if (res != -3) nativefailed++;
02628 }
02629
02630 if (((c0->writeformat != c1->readformat) || (c0->readformat != c1->writeformat) || (c0->nativeformats != o0nativeformats) || (c1->nativeformats != o1nativeformats)) &&
02631 !(c0->generator || c1->generator)) {
02632 if (ast_channel_make_compatible(c0, c1)) {
02633 ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", c0->name, c1->name);
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 return -1;
02641 }
02642 o0nativeformats = c0->nativeformats;
02643 o1nativeformats = c1->nativeformats;
02644 }
02645 who = ast_waitfor_n(cs, 2, &to);
02646 if (!who) {
02647 ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
02648 continue;
02649 }
02650 f = ast_read(who);
02651 if (!f) {
02652 *fo = NULL;
02653 *rc = who;
02654 res = 0;
02655 ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
02656 break;
02657 }
02658
02659 if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
02660 *fo = f;
02661 *rc = who;
02662 res = 0;
02663 ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
02664 break;
02665 }
02666 if ((f->frametype == AST_FRAME_VOICE) ||
02667 (f->frametype == AST_FRAME_TEXT) ||
02668 (f->frametype == AST_FRAME_VIDEO) ||
02669 (f->frametype == AST_FRAME_IMAGE) ||
02670 (f->frametype == AST_FRAME_DTMF)) {
02671 if ((f->frametype == AST_FRAME_DTMF) &&
02672 (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
02673 if ((who == c0)) {
02674 if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
02675 *rc = c0;
02676 *fo = f;
02677
02678 res = 0;
02679 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
02680 break;
02681 } else
02682 goto tackygoto;
02683 } else
02684 if ((who == c1)) {
02685 if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
02686 *rc = c1;
02687 *fo = f;
02688 res = 0;
02689 ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
02690 break;
02691 } else
02692 goto tackygoto;
02693 }
02694 } else {
02695 #if 0
02696 ast_log(LOG_DEBUG, "Read from %s\n", who->name);
02697 if (who == last)
02698 ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
02699 last = who;
02700 #endif
02701 tackygoto:
02702
02703
02704 if (who == c0)
02705 ast_write(c1, f);
02706 else
02707 ast_write(c0, f);
02708 }
02709 ast_frfree(f);
02710 } else
02711 ast_frfree(f);
02712
02713 cs[2] = cs[0];
02714 cs[0] = cs[1];
02715 cs[1] = cs[2];
02716 }
02717 c0->bridge = NULL;
02718 c1->bridge = NULL;
02719 manager_event(EVENT_FLAG_CALL, "Unlink",
02720 "Channel1: %s\r\n"
02721 "Channel2: %s\r\n"
02722 "Uniqueid1: %s\r\n"
02723 "Uniqueid2: %s\r\n",
02724 c0->name, c1->name, c0->uniqueid, c1->uniqueid);
02725 ast_log(LOG_DEBUG, "Bridge stops bridging channels %s and %s\n",c0->name,c1->name);
02726 return res;
02727 }
02728
02729 int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block)
02730 {
02731 int res;
02732 if (chan->pvt->setoption) {
02733 res = chan->pvt->setoption(chan, option, data, datalen);
02734 if (res < 0)
02735 return res;
02736 } else {
02737 errno = ENOSYS;
02738 return -1;
02739 }
02740 if (block) {
02741
02742
02743 ast_log(LOG_ERROR, "XXX Blocking not implemented yet XXX\n");
02744 return -1;
02745 }
02746 return 0;
02747 }
02748
02749 struct tonepair_def {
02750 int freq1;
02751 int freq2;
02752 int duration;
02753 int vol;
02754 };
02755
02756 struct tonepair_state {
02757 float freq1;
02758 float freq2;
02759 float vol;
02760 int duration;
02761 int pos;
02762 int origwfmt;
02763 struct ast_frame f;
02764 unsigned char offset[AST_FRIENDLY_OFFSET];
02765 short data[4000];
02766 };
02767
02768 static void tonepair_release(struct ast_channel *chan, void *params)
02769 {
02770 struct tonepair_state *ts = params;
02771 if (chan) {
02772 ast_set_write_format(chan, ts->origwfmt);
02773 }
02774 free(ts);
02775 }
02776
02777 static void * tonepair_alloc(struct ast_channel *chan, void *params)
02778 {
02779 struct tonepair_state *ts;
02780 struct tonepair_def *td = params;
02781 ts = malloc(sizeof(struct tonepair_state));
02782 if (!ts)
02783 return NULL;
02784 memset(ts, 0, sizeof(struct tonepair_state));
02785 ts->origwfmt = chan->writeformat;
02786 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
02787 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
02788 tonepair_release(NULL, ts);
02789 ts = NULL;
02790 } else {
02791 ts->freq1 = td->freq1;
02792 ts->freq2 = td->freq2;
02793 ts->duration = td->duration;
02794 ts->vol = td->vol;
02795 }
02796
02797 chan->writeinterrupt = 1;
02798 return ts;
02799 }
02800
02801 static int tonepair_generator(struct ast_channel *chan, void *data, int len, int samples)
02802 {
02803 struct tonepair_state *ts = data;
02804 int x;
02805
02806
02807
02808
02809 len = samples * 2;
02810
02811 if (len > sizeof(ts->data) / 2 - 1) {
02812 ast_log(LOG_WARNING, "Can't generate that much data!\n");
02813 return -1;
02814 }
02815 memset(&ts->f, 0, sizeof(ts->f));
02816 for (x=0;x<len/2;x++) {
02817 ts->data[x] = ts->vol * (
02818 sin((ts->freq1 * 2.0 * M_PI / 8000.0) * (ts->pos + x)) +
02819 sin((ts->freq2 * 2.0 * M_PI / 8000.0) * (ts->pos + x))
02820 );
02821 }
02822 ts->f.frametype = AST_FRAME_VOICE;
02823 ts->f.subclass = AST_FORMAT_SLINEAR;
02824 ts->f.datalen = len;
02825 ts->f.samples = samples;
02826 ts->f.offset = AST_FRIENDLY_OFFSET;
02827 ts->f.data = ts->data;
02828 ast_write(chan, &ts->f);
02829 ts->pos += x;
02830 if (ts->duration > 0) {
02831 if (ts->pos >= ts->duration * 8)
02832 return -1;
02833 }
02834 return 0;
02835 }
02836
02837 static struct ast_generator tonepair = {
02838 alloc: tonepair_alloc,
02839 release: tonepair_release,
02840 generate: tonepair_generator,
02841 };
02842
02843 int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
02844 {
02845 struct tonepair_def d = { 0, };
02846 d.freq1 = freq1;
02847 d.freq2 = freq2;
02848 d.duration = duration;
02849 if (vol < 1)
02850 d.vol = 8192;
02851 else
02852 d.vol = vol;
02853 if (ast_activate_generator(chan, &tonepair, &d))
02854 return -1;
02855 return 0;
02856 }
02857
02858 void ast_tonepair_stop(struct ast_channel *chan)
02859 {
02860 ast_deactivate_generator(chan);
02861 }
02862
02863 int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
02864 {
02865 struct ast_frame *f;
02866 int res;
02867 if ((res = ast_tonepair_start(chan, freq1, freq2, duration, vol)))
02868 return res;
02869
02870
02871 while(chan->generatordata && (ast_waitfor(chan, 100) >= 0)) {
02872 f = ast_read(chan);
02873 if (f)
02874 ast_frfree(f);
02875 else
02876 return -1;
02877 }
02878 return 0;
02879 }
02880
02881 unsigned int ast_get_group(char *s)
02882 {
02883 char *copy;
02884 char *piece;
02885 char *c=NULL;
02886 int start=0, finish=0,x;
02887 unsigned int group = 0;
02888 copy = ast_strdupa(s);
02889 if (!copy) {
02890 ast_log(LOG_ERROR, "Out of memory\n");
02891 return 0;
02892 }
02893 c = copy;
02894
02895 while((piece = strsep(&c, ","))) {
02896 if (sscanf(piece, "%d-%d", &start, &finish) == 2) {
02897
02898 } else if (sscanf(piece, "%d", &start)) {
02899
02900 finish = start;
02901 } else {
02902 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece);
02903 return 0;
02904 }
02905 for (x=start;x<=finish;x++) {
02906 if ((x > 31) || (x < 0)) {
02907 ast_log(LOG_WARNING, "Ignoring invalid group %d (maximum group is 31)\n", x);
02908 } else
02909 group |= (1 << x);
02910 }
02911 }
02912 return group;
02913 }