Newer
Older
p->state=MISDN_CLEANING;
misdn_lib_send_event( bc, EVENT_DISCONNECT);
break;
case MISDN_CONNECTED:
/* Alerting or Disconect */
chan_misdn_log(2, bc->port, " --> * State Connected\n");
start_bc_tones(p);
tone_indicate(p, TONE_BUSY);
misdn_lib_send_event( bc, EVENT_DISCONNECT);
p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
break;
Christian Richter
committed
case MISDN_DISCONNECTED:
chan_misdn_log(2, bc->port, " --> * State Disconnected\n");
misdn_lib_send_event( bc, EVENT_RELEASE);
p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
break;
case MISDN_CLEANING:
break;
case MISDN_HOLD_DISCONNECT:
/* need to send release here */
chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
Christian Richter
committed
bc->out_cause=-1;
misdn_lib_send_event(bc,EVENT_RELEASE);
break;
default:
/* Alerting or Disconect */
Christian Richter
committed
Christian Richter
committed
if (bc->nt) {
bc->out_cause=-1;
misdn_lib_send_event(bc, EVENT_RELEASE);
Christian Richter
committed
} else
misdn_lib_send_event(bc, EVENT_DISCONNECT);
p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
}
}
Christian Richter
committed
chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
return 0;
}
Christian Richter
committed
static struct ast_frame *misdn_read(struct ast_channel *ast)
{
struct chan_list *tmp;
char blah[255];
int len =0 ;
if (!ast) return NULL;
Christian Richter
committed
if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
if (!tmp->bc) return NULL;
read(tmp->pipe[0],blah,sizeof(blah));
if (!len) {
chan_misdn_log(4,tmp->bc->port,"misdn_read: ZERO READ\n");
tmp->frame.frametype = AST_FRAME_NULL;
tmp->frame.subclass = 0;
return &tmp->frame;
}
/*shrinken len if necessary, we transmit at maximum 4k*/
len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
tmp->frame.frametype = AST_FRAME_VOICE;
tmp->frame.subclass = AST_FORMAT_ALAW;
tmp->frame.datalen = len;
tmp->frame.samples = len ;
tmp->frame.mallocd =0 ;
tmp->frame.offset= 0 ;
tmp->frame.src = NULL;
tmp->frame.data = tmp->ast_rd_buf ;
return &tmp->frame;
}
Christian Richter
committed
static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
Christian Richter
committed
struct chan_list *ch;
Christian Richter
committed
if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
Christian Richter
committed
if (!ch->bc ) {
ast_log(LOG_WARNING, "private but no bc\n");
return -1;
}
/*if (ch->bc->tone != TONE_NONE)
tone_indicate(ch,TONE_NONE); */
Christian Richter
committed
if (ch->holded ) {
chan_misdn_log(5, ch->bc->port, "misdn_write: Returning because holded\n");
return 0;
}
Christian Richter
committed
if (ch->notxtone) {
chan_misdn_log(5, ch->bc->port, "misdn_write: Returning because notxone\n");
return 0;
}
if ( !frame->subclass) {
chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
return 0;
}
if ( !(frame->subclass & prefformat)) {
Christian Richter
committed
chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
if ( !frame->samples ) {
chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
return 0;
}
if ( ! ch->bc->addr ) {
Christian Richter
committed
chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
#if MISDN_DEBUG
{
int i, max=5>frame->samples?frame->samples:5;
printf("write2mISDN %p %d bytes: ", p, frame->samples);
for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
printf ("\n");
}
#endif
Christian Richter
committed
switch (ch->bc->bc_state) {
case BCHAN_ACTIVATED:
case BCHAN_BRIDGED:
break;
default:
chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch));
return 0;
}
chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
Christian Richter
committed
/*if speech flip bits*/
if ( misdn_cap_is_speech(ch->bc->capability) )
flip_buf_bits(frame->data,frame->samples);
if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
/* Buffered Transmit (triggert by read from isdn side)*/
if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
if (ch->bc->active)
cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
}
} else {
/*transmit without jitterbuffer*/
i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
}
return 0;
}
Christian Richter
committed
enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
struct ast_channel *c1, int flags,
struct ast_frame **fo,
struct ast_channel **rc,
int timeoutms)
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
{
struct chan_list *ch1,*ch2;
struct ast_channel *carr[2], *who;
int to=-1;
struct ast_frame *f;
ch1=get_chan_by_ast(c0);
ch2=get_chan_by_ast(c1);
carr[0]=c0;
carr[1]=c1;
if (ch1 && ch2 ) ;
else
return -1;
int bridging;
misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
if (bridging) {
int ecwb;
misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
ch1->bc->ec_enable=0;
/* manager_ec_disable(ch1->bc); */
misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
ch2->bc->ec_enable=0;
/* manager_ec_disable(ch2->bc); */
}
/* trying to make a mISDN_dsp conference */
chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
Kevin P. Fleming
committed
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
while(1) {
to=-1;
who = ast_waitfor_n(carr, 2, &to);
Christian Richter
committed
break;
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
f = ast_read(who);
if (!f || f->frametype == AST_FRAME_CONTROL) {
/* got hangup .. */
*fo=f;
*rc=who;
break;
}
if (who == c0) {
ast_write(c1,f);
}
else {
ast_write(c0,f);
}
}
if (bridging) {
}
return 0;
}
/** AST INDICATIONS END **/
static int tone_indicate( struct chan_list *cl, enum tone_e tone)
{
const struct tone_zone_sound *ts= NULL;
struct ast_channel *ast=cl->ast;
chan_misdn_log(2,cl->bc->port,"Tone Indicate:\n");
if (!cl->ast) {
return 0;
}
switch (tone) {
case TONE_DIAL:
chan_misdn_log(2,cl->bc->port," --> Dial\n");
ts=ast_get_indication_tone(ast->zone,"dial");
misdn_lib_tone_generator_start(cl->bc);
break;
case TONE_ALERTING:
chan_misdn_log(2,cl->bc->port," --> Ring\n");
ts=ast_get_indication_tone(ast->zone,"ring");
misdn_lib_tone_generator_stop(cl->bc);
break;
case TONE_BUSY:
chan_misdn_log(2,cl->bc->port," --> Busy\n");
ts=ast_get_indication_tone(ast->zone,"busy");
misdn_lib_tone_generator_stop(cl->bc);
break;
case TONE_FILE:
break;
case TONE_NONE:
chan_misdn_log(2,cl->bc->port," --> None\n");
misdn_lib_tone_generator_stop(cl->bc);
ast_playtones_stop(ast);
break;
default:
chan_misdn_log(0,cl->bc->port,"Don't know how to handle tone: %d\n",tone);
}
cl->ts=ts;
if (ts) ast_playtones_start(ast,0, ts->data, 0);
return 0;
}
static int start_bc_tones(struct chan_list* cl)
{
manager_bchannel_activate(cl->bc);
misdn_lib_tone_generator_stop(cl->bc);
cl->notxtone=0;
cl->norxtone=0;
return 0;
}
static int stop_bc_tones(struct chan_list *cl)
{
if (cl->bc) {
manager_bchannel_deactivate(cl->bc);
}
cl->notxtone=1;
cl->norxtone=1;
return 0;
}
Christian Richter
committed
static struct chan_list *init_chan_list(void)
{
struct chan_list *cl=malloc(sizeof(struct chan_list));
if (!cl) {
Christian Richter
committed
chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
return NULL;
}
memset(cl,0,sizeof(struct chan_list));
return cl;
}
static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
{
struct ast_channel *tmp = NULL;
char group[BUFFERSIZE+1]="";
char buf[128];
char buf2[128], *ext=NULL, *port_str;
char *tokb=NULL, *p=NULL;
int channel=0, port=0;
struct misdn_bchannel *newbc = NULL;
struct chan_list *cl=init_chan_list();
Christian Richter
committed
sprintf(buf,"%s/%s",misdn_type,(char*)data);
ast_copy_string(buf2,data, 128);
port_str=strtok_r(buf2,"/", &tokb);
ext=strtok_r(NULL,"/", &tokb);
if (port_str) {
if (port_str[0]=='g' && port_str[1]==':' ) {
/* We make a group call lets checkout which ports are in my group */
port_str += 2;
strncpy(group, port_str, BUFFERSIZE);
group[127] = 0;
chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
}
else if ((p = strchr(port_str, ':'))) {
// we have a preselected channel
*p = 0;
channel = atoi(++p);
port = atoi(port_str);
Christian Richter
committed
chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
}
else {
port = atoi(port_str);
}
} else {
ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
return NULL;
}
if (!ast_strlen_zero(group)) {
char cfg_group[BUFFERSIZE+1];
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
struct robin_list *rr = NULL;
if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
rr = get_robin_position(group);
}
if (rr) {
int robin_channel = rr->channel;
int port_start;
int next_chan = 1;
do {
port_start = 0;
for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
port = misdn_cfg_get_next_port_spin(port)) {
if (!port_start)
port_start = port;
if (port >= port_start)
next_chan = 1;
if (port < port_start && next_chan) {
if (++robin_channel >= MAX_BCHANS) {
robin_channel = 1;
}
next_chan = 0;
}
misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
if (!strcasecmp(cfg_group, group)) {
Christian Richter
committed
int check;
misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
port_up = misdn_lib_port_up(port, check);
if ( port_up ) {
newbc = misdn_lib_get_free_bc(port, robin_channel);
if (newbc) {
chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
chan_misdn_log(4, port, "ortup:%d\n", port_up);
rr->channel = newbc->channel;
break;
}
}
}
}
} while (!newbc && robin_channel != rr->channel);
if (!newbc)
chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
}
else {
for (port=misdn_cfg_get_next_port(0); port > 0;
port=misdn_cfg_get_next_port(port)) {
misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
Christian Richter
committed
chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
if (!strcasecmp(cfg_group, group)) {
Christian Richter
committed
int check;
misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
port_up = misdn_lib_port_up(port, check);
chan_misdn_log(4, port, "portup:%d\n", port_up);
if ( port_up ) {
newbc = misdn_lib_get_free_bc(port, 0);
if (newbc)
break;
}
}
}
}
} else {
if (channel)
chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
newbc = misdn_lib_get_free_bc(port, channel);
}
if (!newbc) {
chan_misdn_log(-1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
chan_misdn_log(-1, 0, " --> SEND: State Down\n");
return NULL;
}
Christian Richter
committed
/* create ast_channel and link all the objects together */
cl->bc=newbc;
Christian Richter
committed
tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
cl->ast=tmp;
/* register chan in local list */
cl_queue_chan(&cl_te, cl) ;
/* fill in the config into the objects */
read_config(cl, ORG_AST);
return tmp;
}
int misdn_send_text (struct ast_channel *chan, const char *text)
{
struct chan_list *tmp=chan->tech_pvt;
if (tmp && tmp->bc) {
ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
} else {
ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
return -1;
}
return 0;
}
Christian Richter
committed
static struct ast_channel_tech misdn_tech = {
.type="mISDN",
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities= AST_FORMAT_ALAW ,
.requester=misdn_request,
.send_digit=misdn_digit,
.call=misdn_call,
.bridge=misdn_bridge,
.hangup=misdn_hangup,
.answer=misdn_answer,
.read=misdn_read,
.write=misdn_write,
.indicate=misdn_indication,
.fixup=misdn_fixup,
.send_text=misdn_send_text,
.properties=0
};
Christian Richter
committed
static struct ast_channel_tech misdn_tech_wo_bridge = {
.type="mISDN",
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities=AST_FORMAT_ALAW ,
.requester=misdn_request,
.send_digit=misdn_digit,
.call=misdn_call,
.hangup=misdn_hangup,
.answer=misdn_answer,
.read=misdn_read,
.write=misdn_write,
.indicate=misdn_indication,
.fixup=misdn_fixup,
.send_text=misdn_send_text,
.properties=0
};
Christian Richter
committed
static unsigned long glob_channel=0;
Christian Richter
committed
static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
{
struct ast_channel *tmp;
tmp = ast_channel_alloc(1);
Christian Richter
committed
chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
if (c<=0) {
c=glob_channel++;
ast_string_field_build(tmp, name, "%s/%d-u%d",
Christian Richter
committed
misdn_type, port, c);
ast_string_field_build(tmp, name, "%s/%d-%d",
Christian Richter
committed
misdn_type, port, c);
}
tmp->nativeformats = prefformat;
Christian Richter
committed
tmp->readformat = format;
tmp->writeformat = format;
tmp->tech_pvt = chlist;
Christian Richter
committed
int bridging;
misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
if (bridging)
tmp->tech = &misdn_tech;
else
tmp->tech = &misdn_tech_wo_bridge;
Christian Richter
committed
tmp->writeformat = format;
tmp->readformat = format;
tmp->priority=1;
if (exten)
Christian Richter
committed
ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
else
chan_misdn_log(1,0,"misdn_new: no exten given.\n");
Christian Richter
committed
if (callerid) {
char *cid_name, *cid_num;
ast_callerid_parse(callerid, &cid_name, &cid_num);
if (cid_name)
tmp->cid.cid_name=strdup(cid_name);
if (cid_num)
tmp->cid.cid_num=strdup(cid_num);
}
{
if (pipe(chlist->pipe)<0)
perror("Pipe failed\n");
tmp->fds[0]=chlist->pipe[0];
}
ast_setstate(tmp, state);
if (state == AST_STATE_RING)
tmp->rings = 1;
else
tmp->rings = 0;
Christian Richter
committed
Christian Richter
committed
chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
return tmp;
}
Christian Richter
committed
static int misdn_tx2ast_frm(struct chan_list * tmp, char * buf, int len )
{
struct ast_frame frame;
/* If in hold state we drop frame .. */
switch(tmp->state) {
case MISDN_CLEANING:
case MISDN_EXTCANTMATCH:
return 0;
case MISDN_WAITING4DIGS:
if (tmp->norxtone) {
chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
return 0;
}
frame.frametype = AST_FRAME_VOICE;
frame.subclass = AST_FORMAT_ALAW;
frame.datalen = len;
frame.samples = len ;
frame.mallocd =0 ;
frame.offset= 0 ;
frame.src = NULL;
frame.data = buf ;
if (tmp->faxdetect || tmp->ast_dsp ) {
struct ast_frame *f,*f2;
if (tmp->trans)
f2=ast_translate(tmp->trans, &frame,0);
else {
return 0;
}
f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
if (f && (f->frametype == AST_FRAME_DTMF)) {
ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
if (f->subclass == 'f' && tmp->faxdetect) {
/* Fax tone -- Handle and return NULL */
struct ast_channel *ast = tmp->ast;
if (!tmp->faxhandled) {
tmp->faxhandled++;
if (strcmp(ast->exten, "fax")) {
if (ast_exists_extension(ast, S_OR(ast->macrocontext, ast->context), "fax", 1, AST_CID_P(ast))) {
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
if (ast_async_goto(ast, ast->context, "fax", 1))
ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
} else
ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
} else
ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
} else
ast_log(LOG_DEBUG, "Fax already handled\n");
frame.frametype = AST_FRAME_NULL;
frame.subclass = 0;
f = &frame;
} else if ( tmp->ast_dsp) {
struct ast_frame fr;
memset(&fr, 0 , sizeof(fr));
fr.frametype = AST_FRAME_DTMF;
fr.subclass = f->subclass ;
fr.src=NULL;
fr.data = NULL ;
fr.datalen = 0;
fr.samples = 0 ;
fr.mallocd =0 ;
fr.offset= 0 ;
chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
ast_queue_frame(tmp->ast, &fr);
frame.frametype = AST_FRAME_NULL;
frame.subclass = 0;
f = &frame;
}
}
}
if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
#if MISDN_DEBUG
int i, max=5>len?len:5;
printf("write2* %p %d bytes: ",tmp, len);
for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
printf ("\n");
#endif
chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
ast_queue_frame(tmp->ast,&frame);
} else {
ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
}
return 0;
}
/** Channel Queue ***/
Christian Richter
committed
static struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
{
struct chan_list *help=list;
for (;help; help=help->next) {
if (help->l3id == l3id ) return help;
}
chan_misdn_log(6, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
return NULL;
}
Christian Richter
committed
static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
{
struct chan_list *help=list;
for (;help; help=help->next) {
if (help->bc == bc) return help;
}
chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
return NULL;
}
Christian Richter
committed
static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
{
struct chan_list *help=list;
chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
for (;help; help=help->next) {
chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
if (help->bc->port == bc->port
&& help->bc->holded ) return help;
}
chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
return NULL;
}
Christian Richter
committed
static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
if (!*list) {
*list = chan;
} else {
struct chan_list *help=*list;
for (;help->next; help=help->next);
help->next=chan;
}
chan->next=NULL;
Christian Richter
committed
static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
{
if (chan->dsp)
ast_dsp_free(chan->dsp);
if (chan->trans)
ast_translator_free_path(chan->trans);
Christian Richter
committed
return;
}
if (*list == chan) {
*list=(*list)->next;
return ;
}
{
struct chan_list *help=*list;
for (;help->next; help=help->next) {
if (help->next == chan) {
help->next=help->next->next;
return;
}
}
}
}
/** Channel Queue End **/
/** Isdn asks us to release channel, pendant to misdn_hangup **/
static void release_chan(struct misdn_bchannel *bc) {
struct ast_channel *ast=NULL;
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
if (!ch) {
chan_misdn_log(0, bc->port, "release_chan: Ch not found!\n");
return;
}
release_lock;
if (ch->ast) {
ast=ch->ast;
}
release_unlock;
chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
Christian Richter
committed
//releaseing jitterbuffer
if (ch->jb ) {
misdn_jb_destroy(ch->jb);
ch->jb=NULL;
} else {
if (!bc->nojitter)
chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
}
if (ch) {
close(ch->pipe[0]);
close(ch->pipe[1]);
if (ast && MISDN_ASTERISK_PVT(ast)) {
chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
chan_misdn_log(3, bc->port, " --> * State Down\n");
/* copy cause */
send_cause2ast(ast,bc);
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
if (ast->_state != AST_STATE_RESERVED) {
chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
ast_setstate(ast, AST_STATE_DOWN);
}
switch(ch->state) {
case MISDN_EXTCANTMATCH:
case MISDN_WAITING4DIGS:
{
chan_misdn_log(3, bc->port, " --> * State Wait4dig | ExtCantMatch\n");
ast_hangup(ast);
}
break;
case MISDN_DIALING:
case MISDN_PROGRESS:
chan_misdn_log(2, bc->port, "* --> In State Dialin\n");
chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
case MISDN_CALLING:
chan_misdn_log(2, bc->port, "* --> In State Callin\n");
if (!bc->nt) {
chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
ast_queue_hangup(ast);
} else {
chan_misdn_log(2, bc->port, "* --> Hangup\n");
ast_queue_hangup(ast);
}
break;
case MISDN_CLEANING:
/* this state comes out of ast so we mustnt call a ast function ! */
chan_misdn_log(2, bc->port, "* --> In StateCleaning\n");
break;
case MISDN_HOLD_DISCONNECT:
break;
default:
chan_misdn_log(2, bc->port, "* --> In State Default\n");
chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
Christian Richter
committed
if (ast) {
ast_queue_hangup(ast);
} else {
chan_misdn_log (0, bc->port, "!! Not really queued!\n");
}
}
}
cl_dequeue_chan(&cl_te, ch);
free(ch);
} else {
/* chan is already cleaned, so exiting */
}
}
}
/*** release end **/
Christian Richter
committed
static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
{
chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
tmp_ch->state=MISDN_HOLD_DISCONNECT;
ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
holded_chan->state=MISDN_CONNECTED;
holded_chan->holded=0;
misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
}
Christian Richter
committed
static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
{
char predial[256]="";
char *p = predial;
struct ast_frame fr;
strncpy(predial, ast->exten, sizeof(predial) -1 );
ch->state=MISDN_DIALING;
Christian Richter
committed
int ret;
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
} else {
int ret;
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
} else {
ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
}
}
Christian Richter
committed
if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio )
chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
else