added lock for sending messages to avoid double sending. shuffled some empty_chans after the cb_event calls, this avoids that a release_complete from a quite different call releases a fresh created setup by accident.

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@61770 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Christian Richter
2007-04-24 13:50:05 +00:00
parent 3682e51ba7
commit f1edea1129
3 changed files with 66 additions and 39 deletions

View File

@@ -1085,6 +1085,10 @@ int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, in
cb_log(8, port, "Init.BC %d.\n",bidx); cb_log(8, port, "Init.BC %d.\n",bidx);
memset(bc, 0,sizeof(struct misdn_bchannel)); memset(bc, 0,sizeof(struct misdn_bchannel));
bc->send_lock=malloc(sizeof(struct send_lock));
pthread_mutex_init(&bc->send_lock->lock, NULL);
if (msn) { if (msn) {
int l = sizeof(bc->msn); int l = sizeof(bc->msn);
@@ -1189,6 +1193,7 @@ struct misdn_stack* stack_init( int midev, int port, int ptp )
stack->nt=1; stack->nt=1;
break; break;
#ifndef MISDN_1_2
case ISDN_PID_L0_TE_U: case ISDN_PID_L0_TE_U:
break; break;
case ISDN_PID_L0_NT_U: case ISDN_PID_L0_NT_U:
@@ -1197,6 +1202,7 @@ struct misdn_stack* stack_init( int midev, int port, int ptp )
break; break;
case ISDN_PID_L0_NT_UP2: case ISDN_PID_L0_NT_UP2:
break; break;
#endif
case ISDN_PID_L0_TE_E1: case ISDN_PID_L0_TE_E1:
cb_log(8, port, "TE S2M Stack\n"); cb_log(8, port, "TE S2M Stack\n");
stack->nt=0; stack->nt=0;
@@ -1521,14 +1527,6 @@ int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_t *frm)
case EVENT_RELEASE_COMPLETE: case EVENT_RELEASE_COMPLETE:
case EVENT_RELEASE: case EVENT_RELEASE:
if (bc->channel>0)
empty_chan_in_stack(stack,bc->channel);
int tmpcause=bc->cause;
int tmp_out_cause=bc->out_cause;
empty_bc(bc);
bc->cause=tmpcause;
bc->out_cause=tmp_out_cause;
clean_up_bc(bc);
break; break;
default: default:
break; break;
@@ -1584,17 +1582,18 @@ int handle_cr ( struct misdn_stack *stack, iframe_t *frm)
cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo); cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo);
if (bc->channel>0) if (bc->channel>0)
empty_chan_in_stack(stack,bc->channel); empty_chan_in_stack(stack,bc->channel);
empty_bc(bc);
clean_up_bc(bc);
dump_chan_list(stack);
/*bc->pid = 0;*/ /*bc->pid = 0;*/
bc->need_disconnect=0; bc->need_disconnect=0;
bc->need_release=0; bc->need_release=0;
bc->need_release_complete=0; bc->need_release_complete=0;
cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data);
empty_bc(bc);
clean_up_bc(bc);
dump_chan_list(stack);
if (bc->stack_holder) { if (bc->stack_holder) {
cb_log(4,stack->port, "REMOVEING Holder\n"); cb_log(4,stack->port, "REMOVEING Holder\n");
stack_holder_remove( stack, bc); stack_holder_remove( stack, bc);
@@ -2653,6 +2652,18 @@ int handle_frm(msg_t *msg)
} }
} }
if (event == EVENT_RELEASE_COMPLETE) {
/* release bchannel only after we've anounced the RELEASE_COMPLETE */
if (bc->channel>0)
empty_chan_in_stack(stack,bc->channel);
int tmpcause=bc->cause;
int tmp_out_cause=bc->out_cause;
empty_bc(bc);
bc->cause=tmpcause;
bc->out_cause=tmp_out_cause;
clean_up_bc(bc);
}
cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim); cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim);
@@ -3167,21 +3178,37 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc)
cb_log(5, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder); cb_log(5, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);
} }
#define RETURN(a,b) {retval=a; goto b;}
void misdn_send_lock(struct misdn_bchannel *bc)
{
//cb_log(0,bc->port,"Locking bc->pid:%d\n", bc->pid);
pthread_mutex_lock(&bc->send_lock->lock);
}
void misdn_send_unlock(struct misdn_bchannel *bc)
{
//cb_log(0,bc->port,"UnLocking bc->pid:%d\n", bc->pid);
pthread_mutex_unlock(&bc->send_lock->lock);
}
int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
{ {
msg_t *msg; msg_t *msg;
int err = -1 ; int retval=0;
int ret=0;
if (!bc) goto ERR; if (!bc) RETURN(-1,OUT_POST_UNLOCK);
struct misdn_stack *stack=get_stack_by_bc(bc); struct misdn_stack *stack=get_stack_by_bc(bc);
if (!stack) { if (!stack) {
cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad); cb_log(0,bc->port,"SENDEVENT: no Stack for event:%s oad:%s dad:%s \n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad);
return -1; RETURN(-1,OUT);
} }
misdn_send_lock(bc);
cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->uperid:%x\n",stack->nt, stack->upper_id); cb_log(6,stack->port,"SENDEVENT: stack->nt:%d stack->uperid:%x\n",stack->nt, stack->upper_id);
if ( stack->nt && !stack->l1link) { if ( stack->nt && !stack->l1link) {
@@ -3189,7 +3216,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
bc->evq=event; bc->evq=event;
cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0)); cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0));
misdn_lib_get_l1_up(stack); misdn_lib_get_l1_up(stack);
return 0; RETURN(0,OUT);
} }
cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid); cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s pid:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, bc->pid);
@@ -3201,8 +3228,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
if (create_process(glob_mgr->midev, bc)<0) { if (create_process(glob_mgr->midev, bc)<0) {
cb_log(0, stack->port, " No free channel at the moment @ send_event\n"); cb_log(0, stack->port, " No free channel at the moment @ send_event\n");
err=-ENOCHAN; RETURN(-ENOCHAN,OUT);
goto ERR;
} }
#if 0 #if 0
if (stack->nt) { if (stack->nt) {
@@ -3218,8 +3244,6 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
case EVENT_ALERTING: case EVENT_ALERTING:
case EVENT_PROCEEDING: case EVENT_PROCEEDING:
case EVENT_SETUP_ACKNOWLEDGE: case EVENT_SETUP_ACKNOWLEDGE:
if (!bc->nt && !stack->ptp) break;
case EVENT_CONNECT: case EVENT_CONNECT:
case EVENT_RETRIEVE_ACKNOWLEDGE: case EVENT_RETRIEVE_ACKNOWLEDGE:
@@ -3229,21 +3253,19 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
if (!bc->channel) { if (!bc->channel) {
cb_log(0, stack->port, " No free channel at the moment\n"); cb_log(0, stack->port, " No free channel at the moment\n");
/*FIXME: add disconnect*/ /*FIXME: add disconnect*/
err=-ENOCHAN; RETURN(-ENOCHAN,OUT);
goto ERR;
} }
if (set_chan_in_stack(stack ,bc->channel)<0) { if (set_chan_in_stack(stack ,bc->channel)<0) {
/*FIXME: add disconnect*/ /*FIXME: add disconnect*/
err=-ENOCHAN; RETURN(-ENOCHAN,OUT);
goto ERR;
} }
} }
/* Its that i generate channels */ /* Its that i generate channels */
} }
ret=setup_bc(bc); retval=setup_bc(bc);
if (ret == -EINVAL) { if (retval == -EINVAL) {
cb_log(0,bc->port,"send_event: setup_bc failed\n"); cb_log(0,bc->port,"send_event: setup_bc failed\n");
} }
@@ -3276,7 +3298,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel)); struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel));
if (!holded_bc) { if (!holded_bc) {
cb_log(0,bc->port, "Could not allocate holded_bc!!!\n"); cb_log(0,bc->port, "Could not allocate holded_bc!!!\n");
return -1; RETURN(-1,OUT);
} }
/*backup the bc*/ /*backup the bc*/
@@ -3311,7 +3333,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
case EVENT_DISCONNECT: case EVENT_DISCONNECT:
if (!bc->need_disconnect) { if (!bc->need_disconnect) {
cb_log(0,bc->port," --> we have already send Disconnect\n"); cb_log(0,bc->port," --> we have already send Disconnect\n");
return -1; RETURN(-1,OUT);
} }
bc->need_disconnect=0; bc->need_disconnect=0;
@@ -3319,7 +3341,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
case EVENT_RELEASE: case EVENT_RELEASE:
if (!bc->need_release) { if (!bc->need_release) {
cb_log(0,bc->port," --> we have already send Release\n"); cb_log(0,bc->port," --> we have already send Release\n");
return -1; RETURN(-1,OUT);
} }
bc->need_disconnect=0; bc->need_disconnect=0;
bc->need_release=0; bc->need_release=0;
@@ -3327,7 +3349,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
case EVENT_RELEASE_COMPLETE: case EVENT_RELEASE_COMPLETE:
if (!bc->need_release_complete) { if (!bc->need_release_complete) {
cb_log(0,bc->port," --> we have already send Release_complete\n"); cb_log(0,bc->port," --> we have already send Release_complete\n");
return -1; RETURN(-1,OUT);
} }
bc->need_disconnect=0; bc->need_disconnect=0;
bc->need_release=0; bc->need_release=0;
@@ -3349,13 +3371,12 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
case EVENT_CONNECT_ACKNOWLEDGE: case EVENT_CONNECT_ACKNOWLEDGE:
if ( bc->nt || misdn_cap_is_speech(bc->capability)) { if ( bc->nt || misdn_cap_is_speech(bc->capability)) {
int ret=setup_bc(bc); int retval=setup_bc(bc);
if (ret == -EINVAL){ if (retval == -EINVAL){
cb_log(0,bc->port,"send_event: setup_bc failed\n"); cb_log(0,bc->port,"send_event: setup_bc failed\n");
} }
} }
if (misdn_cap_is_speech(bc->capability)) { if (misdn_cap_is_speech(bc->capability)) {
if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0); if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0);
@@ -3381,10 +3402,11 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event )
msg_queue_tail(&stack->downqueue, msg); msg_queue_tail(&stack->downqueue, msg);
sem_post(&glob_mgr->new_msg); sem_post(&glob_mgr->new_msg);
return 0; OUT:
misdn_send_unlock(bc);
ERR:
return -1; OUT_POST_UNLOCK:
return retval;
} }

View File

@@ -213,6 +213,7 @@ union facility {
struct misdn_bchannel { struct misdn_bchannel {
struct send_lock *send_lock;
int nt; int nt;
int port; int port;

View File

@@ -24,6 +24,10 @@
ibuffer_t *astbuf; ibuffer_t *astbuf;
ibuffer_t *misdnbuf; ibuffer_t *misdnbuf;
struct send_lock {
pthread_mutex_t lock;
};
struct isdn_msg { struct isdn_msg {
unsigned long misdn_msg; unsigned long misdn_msg;