diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c index bb292dca2545adbf2b726f348340166238835962..989d6000bc2cca6ef3adb5652c6857739bed874b 100644 --- a/src/channels/chan_voicemngr.c +++ b/src/channels/chan_voicemngr.c @@ -153,6 +153,7 @@ static const char config[] = "chan_telephony.conf"; static const char broadcast_path[] = "voice.line"; static channel_settings channel_config[MAX_NUM_LINEID]; static struct line_stats_t line_stats[MAX_SIP_CLIENTS]; +static int sip_line_callmode[MAX_SIP_CLIENTS] = {[0 ... MAX_SIP_CLIENTS-1] = LINE_CALL_MODE_MULTIPLE}; static int current_connection_id = 0; static int num_fxs_endpoints = -1; static int num_fxo_endpoints = -1; @@ -473,6 +474,8 @@ static struct endpt_event event_map[] = { { .name = "SWITCH", .event = EVENT_SWITCH }, { .name = "JOIN", .event = EVENT_JOIN }, { .name = "RELEASE", .event = EVENT_RELEASE }, + { .name = "LINE_CALL_MODE_SINGLE", .event = EVENT_LINE_CALL_MODE_SINGLE}, + { .name = "LINE_CALL_MODE_MULTIPLE", .event = EVENT_LINE_CALL_MODE_MULTIPLE}, { .name = "", .event = EVENT_LAST }, }; @@ -1292,8 +1295,10 @@ static int chan_voicemngr_call(struct ast_channel *chan, const char *dest, int t struct timeval UtcTime = ast_tvnow(); struct ast_tm tm; sub = ast_channel_tech_pvt(chan); + int sip_client_id = -1; ast_debug(1, "line %d\n", sub->parent->line_id); + sscanf(sub->parent->context, "sip%d", &sip_client_id); ast_localtime(&UtcTime, &tm, NULL); if ((ast_channel_state(chan) != AST_STATE_DOWN) && (ast_channel_state(chan) != AST_STATE_RESERVED)) { @@ -1337,7 +1342,8 @@ static int chan_voicemngr_call(struct ast_channel *chan, const char *dest, int t ast_setstate(chan, AST_STATE_RINGING_CW); ast_queue_control(chan, AST_CONTROL_RINGING_CW); } - else if (!chan_voicemngr_subchannel_is_idle(sub_peer)) { + else if (!chan_voicemngr_subchannel_is_idle(sub_peer) || + (has_call_in_sip_client(p->context) && sip_line_callmode[sip_client_id] == LINE_CALL_MODE_SINGLE) ) { ast_debug(1, "Line is busy\n"); ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY); ast_queue_control(chan, AST_CONTROL_BUSY); @@ -2873,9 +2879,11 @@ static void handle_dect_event(struct chan_voicemngr_subchannel *sub, struct chan } else if (event == EVENT_RELEASE) { ast_log(LOG_NOTICE, "EVENT_RELEASE detected for phone line %d\n", sub->parent->line_id); - if (sub->channel_state == INCALL && sub_peer->channel_state != CALLWAITING) { - ast_log(LOG_ERROR, "Hanging up call\n"); - ast_queue_control(owner, AST_CONTROL_HANGUP); + if (sub->channel_state == AWAITONHOOK && sub_peer->channel_state == ONHOOK) { + chan_voicemngr_close_connection(sub); + } else if (sub->channel_state == INCALL && sub_peer->channel_state != CALLWAITING) { + ast_log(LOG_ERROR, "Hanging up call\n"); + ast_queue_control(owner, AST_CONTROL_HANGUP); } else if ((sub->channel_state == RINGBACK || sub->channel_state == CALLENDED) && sub_peer->channel_state == ONHOLD) { endpt_signal(sub->parent->line_id, "ringback", "off", NULL); ast_queue_control(owner, AST_CONTROL_HANGUP); @@ -3359,6 +3367,18 @@ static void chan_voicemngr_process_event(struct endpt_event *ev) if (sub) { switch (ev->event) { case EVENT_OFFHOOK: { + int sip_client_id = -1; + sscanf(sub->parent->context, "sip%d", &sip_client_id); + if (has_call_in_sip_client(p->context) && sip_line_callmode[sip_client_id] == LINE_CALL_MODE_SINGLE) { + ast_log(LOG_NOTICE, "The call cannot be proceeded. Line is in single call mode and other extension is in call!\n"); + chan_voicemngr_create_connection(sub); + p->dialtone = DIALTONE_UNOBTAINABLE; + sub->channel_state = AWAITONHOOK; + p->dialtone_timeout_timer_id = ast_sched_add(sched, channel_config[p->line_id].offhook_nu_timeoutmsec, handle_dialtone_timeout, p); + chan_voicemngr_signal_dialtone(p); + break; + } + if (!strlen(p->extensionCallStatus) || sub->channel_state == ONHOOK) strncpy(p->extensionCallStatus, "Dialing", CALL_STATUS_MAX_LEN); else if (sub->channel_state == RINGING) @@ -3573,6 +3593,11 @@ static void chan_voicemngr_process_event(struct endpt_event *ev) ast_debug(1, "EVENT %d from dect received\n", ev->event); handle_dect_event(sub, sub_peer, owner, peer_owner, ev->event); break; + case EVENT_LINE_CALL_MODE_SINGLE: + case EVENT_LINE_CALL_MODE_MULTIPLE: + ast_debug(1, "EVENT %d from dect received\n", ev->event); + sip_line_callmode[ev->line] = ev->event == EVENT_LINE_CALL_MODE_SINGLE ? LINE_CALL_MODE_SINGLE : LINE_CALL_MODE_MULTIPLE; + default: ast_debug(1, "Ignore event %s\n", ev->name); break; diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h index a61cfb99361e14cf1df3b5618499fdb92401f9d1..5dc9832d971ded469979de6aca3fb748b4e06b87 100644 --- a/src/channels/chan_voicemngr.h +++ b/src/channels/chan_voicemngr.h @@ -83,6 +83,8 @@ enum LINE_EVENT { // Events from low level line (endpoint etc.) EVENT_SWITCH, EVENT_JOIN, EVENT_RELEASE, + EVENT_LINE_CALL_MODE_SINGLE, + EVENT_LINE_CALL_MODE_MULTIPLE, EVENT_LAST, }; @@ -97,6 +99,12 @@ enum CALL_DIRECTION { OUTGOING_CALL, }; +enum LINE_CALL_MODE { + LINE_CALL_MODE_SINGLE, + LINE_CALL_MODE_MULTIPLE, +}; + + typedef enum dialtone_state { DIALTONE_OFF = 0, DIALTONE_ON,