diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c index c2e5f5f7fa78988a191de5e7e556e6242bf4815d..29f09ca17fa492e1bdc7c56f4dbe6a802388c8dc 100644 --- a/channels/chan_brcm.c +++ b/channels/chan_brcm.c @@ -560,26 +560,22 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat struct ast_frame astFrame; int res = 0; - ast_debug(2, "Channel %s gets an indication, condition = %d\n", ast_channel_name(ast), condition); + ast_log(LOG_NOTICE, "Channel %s gets an indication, condition = %d, sub->channel_state: %s\n", ast_channel_name(ast), + condition, state2str(sub->channel_state)); - pvt_lock(sub->parent, "indicate"); - //ast_mutex_lock(&sub->parent->lock); switch(condition) { case AST_CONTROL_UNHOLD: + pvt_lock(sub->parent, "indicate"); brcm_stop_dialtone(sub->parent); - + pvt_unlock(sub->parent); // Play a beep when unholding. - ast_channel_lock(ast); play_bridge_channel = ast_channel_get_bridge_channel(ast); - ast_channel_unlock(ast); ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, "beep", NULL); sub->channel_state = INCALL; // Tell all participants to re-sync RTP stream. - ast_channel_lock(ast); myBridge = ast_channel_internal_bridge(ast); - ast_channel_unlock(ast); memset(&astFrame, 0, sizeof astFrame); astFrame.frametype = AST_FRAME_CONTROL; astFrame.subclass.integer = AST_CONTROL_SRCUPDATE; @@ -589,11 +585,14 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat case AST_CONTROL_UPDATE_RTP_PEER: case AST_CONTROL_SRCUPDATE: case AST_CONTROL_SRCCHANGE: + pvt_lock(sub->parent, "indicate"); sub->codec = -1; if (sub->channel_state == RINGBACK) endpt_signal(sub->parent->line_id, "ringback", "off", NULL); + pvt_unlock(sub->parent); break; case AST_CONTROL_RINGING: + pvt_lock(sub->parent, "indicate"); ast_debug(4, "Got AST_CONTROL_RINGING on %s, sub->codec = %d\n", ast_channel_name(ast), sub->codec); sub->channel_state = RINGBACK; // Play local ringback tone only if there is no incoming media packet @@ -603,6 +602,7 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat sub->call_id = ast_channel_callid(sub->owner); endpt_connection(sub->parent->line_id, sub->call_id, "update"); } + pvt_unlock(sub->parent); break; case AST_CONTROL_UNHOLD_FOR_TRANSFER: if (sub->channel_state == TRANSFERING) { @@ -652,6 +652,7 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat res = -1; break; case AST_CONTROL_CONNECTED_LINE: + pvt_lock(sub->parent, "indicate"); res = -1; ast_debug(4, "Got CONNECTED LINE UPDATE on %s\n", ast_channel_name(ast)); /* Update caller IDs on display - dect ? */ @@ -689,8 +690,8 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat endpt_connection(sub->parent->line_id, sub->call_id, "update"); res = 0; } + pvt_unlock(sub->parent); break; - case AST_CONTROL_BUSY: ast_debug(4, "Got BUSY on %s\n", ast_channel_name(ast)); /* The other end is busy */ @@ -709,56 +710,61 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat res = -1; break; case AST_CONTROL_NORMAL_DIALTONE: + pvt_lock(sub->parent, "indicate"); brcm_dialtone_set(sub->parent, DIALTONE_ON); + pvt_unlock(sub->parent); break; case AST_CONTROL_SPECIAL_DIALTONE: + pvt_lock(sub->parent, "indicate"); brcm_dialtone_set(sub->parent, DIALTONE_SPECIAL_CONDITION); + pvt_unlock(sub->parent); break; - case AST_CONTROL_PVT_CAUSE_CODE: { - const struct ast_control_pvt_cause_code *cause_code = data; - int ast_cause = cause_code->ast_cause; - ast_debug(2, "AST_CONTROL_PVT_CAUSE_CODE = %d, chan_name = %s\n", ast_cause, cause_code->chan_name); - - switch (ast_cause) { - case AST_CAUSE_NO_USER_RESPONSE: - case AST_CAUSE_NO_ANSWER: - case AST_CAUSE_CALL_REJECTED: - endpt_signal(sub->parent->line_id, "ringback", "off", NULL); - if (ast_channel_state(ast) != AST_STATE_UP) { - endpt_signal(sub->parent->line_id, "congestion", "on", NULL); - strncpy(sub->parent->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN); - break; - } - res = -1; - break; + case AST_CONTROL_PVT_CAUSE_CODE: + pvt_lock(sub->parent, "indicate"); + const struct ast_control_pvt_cause_code *cause_code = data; + int ast_cause = cause_code->ast_cause; + ast_debug(2, "AST_CONTROL_PVT_CAUSE_CODE = %d, chan_name = %s\n", ast_cause, cause_code->chan_name); + + switch (ast_cause) { + case AST_CAUSE_NO_USER_RESPONSE: + case AST_CAUSE_NO_ANSWER: + case AST_CAUSE_CALL_REJECTED: + endpt_signal(sub->parent->line_id, "ringback", "off", NULL); + if (ast_channel_state(ast) != AST_STATE_UP) { + endpt_signal(sub->parent->line_id, "congestion", "on", NULL); + strncpy(sub->parent->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN); + break; + } + res = -1; + break; case AST_CAUSE_NORMAL_CLEARING: - // This is just fine. - break; + // This is just fine. + break; case AST_CAUSE_USER_BUSY: - endpt_signal(sub->parent->line_id, "ringback", "off", NULL); - if (ast_channel_state(ast) != AST_STATE_UP) { - /* XXX We should play a busy tone here!! */ - sub->channel_state = CALLENDED; - endpt_signal(sub->parent->line_id, "busy", "on", NULL); - strncpy(sub->parent->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN); - break; - } - res = -1; + endpt_signal(sub->parent->line_id, "ringback", "off", NULL); + if (ast_channel_state(ast) != AST_STATE_UP) { + /* XXX We should play a busy tone here!! */ + sub->channel_state = CALLENDED; + endpt_signal(sub->parent->line_id, "busy", "on", NULL); + strncpy(sub->parent->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN); + break; + } + res = -1; case AST_CAUSE_NETWORK_OUT_OF_ORDER: - brcm_stop_dialtone(sub->parent); // stop any dialtone exist if disconnection happened due to network/server - break; + brcm_stop_dialtone(sub->parent); // stop any dialtone exist if disconnection happened due to network/server + break; default: - ast_debug(1, "Don't know how to handle cause code %d\n", ast_cause); - break; - } + ast_debug(1, "Don't know how to handle cause code %d\n", ast_cause); + break; } + pvt_unlock(sub->parent); break; default: res = -1; ast_debug(1, "Don't know how to indicate condition %d\n", condition); break; } - pvt_unlock(sub->parent); + return res; } @@ -777,7 +783,9 @@ static int brcm_getRtpStats(struct ast_channel *ast) if (endpt_get_rtp_stats(sub->parent->line_id)) { ast_log(LOG_WARNING, "Unable to get RTP statistics\n"); } + ast_channel_lock(ast); ast_channel_rtpStats_set(ast, &sub->rtp_stats); + ast_channel_unlock(ast); } pvt_unlock(sub->parent); @@ -1108,9 +1116,9 @@ static int brcm_hangup(struct ast_channel *ast) pvt_lock(p, "TELCHAN hangup"); sub_peer = brcm_subchannel_get_peer(sub); - ast_debug(1, "ast=%s line_id=%d connection_id=%d dialtone=%s channel_state=%s peer_state=%s\n", + ast_log(LOG_NOTICE, "brcm_hangup chan=%s line_id=%d connection_id=%d dialtone=%s channel_state=%s peer_state=%s sub_timer: %d, peer_timer: %d\n", ast_channel_name(ast), p->line_id, sub->connection_id, dialtone_map[p->dialtone].str, - state2str(sub->channel_state), state2str(sub_peer->channel_state)); + state2str(sub->channel_state), state2str(sub_peer->channel_state), sub->conf_timer_id, sub_peer->conf_timer_id); /* If call is not connected (INCALL) or is dialing but Subchannel is busy, move to Disconnected state */ if ((sub->channel_state!= ONHOOK && sub_peer->channel_state != OFFHOOK)) { @@ -1225,9 +1233,11 @@ static int brcm_hangup(struct ast_channel *ast) ast_channel_ref(sub_peer->owner); peer_owner = sub_peer->owner; pvt_unlock(sub_peer->parent); - brcm_unmute_connection(sub_peer); - ast_queue_unhold(peer_owner); - sub_peer->channel_state = INCALL; + if (peer_owner) { + brcm_unmute_connection(sub_peer); + ast_queue_unhold(peer_owner); + sub_peer->channel_state = INCALL; + } } memset(p->ext, 0, sizeof(p->ext)); @@ -1745,14 +1755,14 @@ static int setup_conference_call_cb( const void *data) /* Setup conference if no dtmf is pressed after flash ,i.e we are not waiting for dtmf now*/ if((sub->conf_timer_id != -1) || (sub_peer->conf_timer_id != -1)) { + sub->conf_timer_id = -1; + sub_peer->conf_timer_id = -1; ast_log(LOG_NOTICE,"Valid flags to start a Conference Call\n"); brcm_create_conference(p); if (peer_owner) { sub_peer->channel_state = INCALL; } sub->channel_state = INCALL; - sub->conf_timer_id = -1; - sub_peer->conf_timer_id = -1; } brcm_send_ubus_event("UNHOLD",sub->parent->line_id); @@ -4361,17 +4371,15 @@ static int asterisk_event(struct ubus_context *ctx, struct ubus_object *obj, char *event_str; struct endpt_event *ev; int line; - + ast_log(LOG_DEBUG, "Event received!\n"); blobmsg_parse(asterisk_event_policy, __EVENT_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[EVENT_LINE_ID] || !tb[EVENT_TYPE]) + if (!tb[EVENT_LINE_ID] || !tb[EVENT_TYPE]) { + ast_log(LOG_DEBUG, "Wrong param: tb[EVENT_LINE_ID]: %d, tb[EVENT_TYPE]: %d\n", tb[EVENT_LINE_ID], tb[EVENT_TYPE]); return UBUS_STATUS_INVALID_ARGUMENT; - + } line = blobmsg_get_u32(tb[EVENT_LINE_ID]); - event_str = blobmsg_get_string(tb[EVENT_TYPE]); - /* Check if event is valid */ for (ev = event_map; ev->event != EVENT_LAST; ev++) { if (strncmp(ev->name, event_str, strlen(ev->name)) == 0) @@ -4857,16 +4865,13 @@ static int brcm_create_conference(struct brcm_pvt *p) ast_queue_unhold(second->owner); onhold->channel_state = INCALL; sched_yield(); - // Move second call into first bridge and wait for it to finish. chanToKick[0] = second->owner; - pvt_lock(second->parent, "moving call to first bridge"); if(onholdBridge && secondBridge) - res = ast_bridge_merge(onholdBridge, secondBridge, 0, chanToKick, 1); + res = ast_bridge_merge(onholdBridge, secondBridge, 0, chanToKick, 1); while(ast_bridge_find_by_id(second->conference_id)) sched_yield(); pvt_unlock(second->parent); - // SIP calls need unhold sent to the bridge as well. astFrame.frametype = AST_FRAME_CONTROL; astFrame.subclass.integer = AST_CONTROL_UNHOLD; diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 9f19af12d16082378235dbc61b38a01635abfef9..837ccecbdeddfa31bdc24ec7ddd01c606493928b 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -2259,7 +2259,12 @@ static int transfer(void *data) target = contact->uri; } } - transfer_refer(trnf_data->session, target); + + if (ast_channel_state(trnf_data->session->channel) == AST_STATE_RING) { + transfer_redirect(trnf_data->session, target); + } else { + transfer_refer(trnf_data->session, target); + } } ao2_ref(trnf_data, -1);