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