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