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