diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 3c1530c64c..d9daf6514e 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -264,12 +264,15 @@ struct register_ack_message { #define START_TONE_MESSAGE 0x0082 struct start_tone_message { uint32_t tone; - uint32_t space[3]; + uint32_t space; + uint32_t instance; + uint32_t reference; }; #define STOP_TONE_MESSAGE 0x0083 struct stop_tone_message { - uint32_t space[2]; + uint32_t instance; + uint32_t reference; }; #define SET_RINGER_MESSAGE 0x0085 @@ -723,6 +726,7 @@ union skinny_data { struct clear_prompt_message clearpromptstatus; struct definetimedate_message definetimedate; struct start_tone_message starttone; + struct stop_tone_message stoptone; struct speed_dial_stat_res_message speeddial; struct line_state_req_message line; struct line_stat_res_message linestat; @@ -1489,16 +1493,6 @@ static void transmit_callstate(struct skinnysession *s, int instance, int state, { struct skinny_req *req; - if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE))) - return; - - if (state == SKINNY_ONHOOK) { - transmit_speaker_mode(s, SKINNY_SPEAKEROFF); - } - req->data.callstate.callState = htolel(state); - req->data.callstate.lineInstance = htolel(instance); - req->data.callstate.callReference = htolel(callid); - transmit_response(s, req); if (state == SKINNY_OFFHOOK) { if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE))) return; @@ -1506,6 +1500,8 @@ static void transmit_callstate(struct skinnysession *s, int instance, int state, req->data.activatecallplane.lineInstance = htolel(instance); transmit_response(s, req); } else if (state == SKINNY_ONHOOK) { + transmit_speaker_mode(s, SKINNY_SPEAKEROFF); + if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE))) return; @@ -1515,17 +1511,25 @@ static void transmit_callstate(struct skinnysession *s, int instance, int state, if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE))) return; - req->data.closereceivechannel.conferenceId = 0; + req->data.closereceivechannel.conferenceId = htolel(callid); req->data.closereceivechannel.partyId = htolel(callid); transmit_response(s, req); if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE))) return; - req->data.stopmedia.conferenceId = 0; + req->data.stopmedia.conferenceId = htolel(callid); req->data.stopmedia.passThruPartyId = htolel(callid); transmit_response(s, req); } + + if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE))) + return; + + req->data.callstate.callState = htolel(state); + req->data.callstate.lineInstance = htolel(instance); + req->data.callstate.callReference = htolel(callid); + transmit_response(s, req); } static void transmit_callinfo(struct skinnysession *s, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype) @@ -1567,7 +1571,7 @@ static void transmit_connect(struct skinnysession *s, struct skinny_subchannel * fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability)); - req->data.openreceivechannel.conferenceId = htolel(0); + req->data.openreceivechannel.conferenceId = htolel(sub->callid); req->data.openreceivechannel.partyId = htolel(sub->callid); req->data.openreceivechannel.packets = htolel(fmt.cur_ms); req->data.openreceivechannel.capability = htolel(codec_ast2skinny(fmt.bits)); @@ -1576,7 +1580,7 @@ static void transmit_connect(struct skinnysession *s, struct skinny_subchannel * transmit_response(s, req); } -static void transmit_tone(struct skinnysession *s, int tone) +static void transmit_tone(struct skinnysession *s, int tone, int instance, int reference) { struct skinny_req *req; @@ -1588,9 +1592,14 @@ static void transmit_tone(struct skinnysession *s, int tone) if (tone > 0) { if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE))) return; + req->data.starttone.tone = htolel(tone); + req->data.starttone.instance = htolel(instance); + req->data.starttone.reference = htolel(reference); } else { if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE))) return; + req->data.stoptone.instance = htolel(instance); + req->data.stoptone.reference = htolel(reference); } if (tone > 0) { @@ -1651,7 +1660,7 @@ static void transmit_ringer_mode(struct skinnysession *s, int mode) transmit_response(s, req); } -static void transmit_displaymessage(struct skinnysession *s, const char *text) +static void transmit_displaymessage(struct skinnysession *s, const char *text, int instance, int reference) { struct skinny_req *req; @@ -1659,6 +1668,9 @@ static void transmit_displaymessage(struct skinnysession *s, const char *text) if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE))) return; + req->data.clearpromptstatus.lineInstance = instance; + req->data.clearpromptstatus.callReference = reference; + if (skinnydebug) ast_verbose("Clearing Display\n"); } else { @@ -2305,7 +2317,7 @@ static void *skinny_newcall(void *data) res = ast_pbx_run(c); if (res) { ast_log(LOG_WARNING, "PBX exited non-zero\n"); - transmit_tone(s, SKINNY_REORDER); + transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid); } return NULL; } @@ -2341,8 +2353,8 @@ static void *skinny_ss(void *data) len = strlen(d->exten); - if (len && !ast_ignore_pattern(c->context, d->exten)) { - transmit_tone(s, SKINNY_SILENCE); + if (!ast_ignore_pattern(c->context, d->exten)) { + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); } if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) { @@ -2353,7 +2365,7 @@ static void *skinny_ss(void *data) if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n", l->call_forward, c->name); - transmit_tone(s, SKINNY_DIALTONE); + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); if (res) { break; } @@ -2361,7 +2373,7 @@ static void *skinny_ss(void *data) ast_indicate(c, -1); ast_safe_sleep(c, 1000); memset(d->exten, 0, sizeof(d->exten)); - transmit_tone(s, SKINNY_DIALTONE); + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); len = 0; getforward = 0; } else { @@ -2379,7 +2391,7 @@ static void *skinny_ss(void *data) } else if (res == 0) { ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n"); memset(d->exten, 0, sizeof(d->exten)); - transmit_tone(s, SKINNY_REORDER); + transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid); if (sub->owner && sub->owner->_state != AST_STATE_UP) { ast_indicate(c, -1); ast_hangup(c); @@ -2389,7 +2401,7 @@ static void *skinny_ss(void *data) ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) { ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten, c->cid.cid_num ? c->cid.cid_num : "", c->context); memset(d->exten, 0, sizeof(d->exten)); - transmit_tone(s, SKINNY_REORDER); + transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid); /* hang out for 3 seconds to let congestion play */ ast_safe_sleep(c, 3000); break; @@ -2486,10 +2498,9 @@ static int skinny_hangup(struct ast_channel *ast) transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF); transmit_speaker_mode(s, SKINNY_SPEAKEROFF); } else if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_ONHOOK)) { + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid); - transmit_speaker_mode(s, SKINNY_SPEAKEROFF); transmit_ringer_mode(s, SKINNY_RING_OFF); - transmit_tone(s, SKINNY_SILENCE); transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF); do_housekeeping(s); } @@ -2525,7 +2536,7 @@ static int skinny_answer(struct ast_channel *ast) ast_setstate(ast, AST_STATE_UP); } - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); /* order matters here... for some reason, transmit_callinfo must be before transmit_callstate, or you won't get keypad messages in some situations. */ @@ -2648,7 +2659,7 @@ static int skinny_senddigit_end(struct ast_channel *ast, char digit, unsigned in int tmp; /* not right */ sprintf(tmp, "%d", digit); - transmit_tone(d->session, digit); + transmit_tone(d->session, digit, l->instance, sub->callid); #endif return -1; /* Stop inband indications */ } @@ -2715,7 +2726,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s case AST_CONTROL_RINGING: if (ast->_state != AST_STATE_UP) { if (!sub->progress) { - transmit_tone(s, SKINNY_ALERT); + transmit_tone(s, SKINNY_ALERT, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid); transmit_dialednumber(s, ast->exten, l->instance, sub->callid); transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid); @@ -2727,7 +2738,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s return -1; case AST_CONTROL_BUSY: if (ast->_state != AST_STATE_UP) { - transmit_tone(s, SKINNY_BUSYTONE); + transmit_tone(s, SKINNY_BUSYTONE, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_BUSY, sub->callid); sub->alreadygone = 1; ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); @@ -2736,7 +2747,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s return -1; case AST_CONTROL_CONGESTION: if (ast->_state != AST_STATE_UP) { - transmit_tone(s, SKINNY_REORDER); + transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_CONGESTION, sub->callid); sub->alreadygone = 1; ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); @@ -2745,7 +2756,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s return -1; case AST_CONTROL_PROGRESS: if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) { - transmit_tone(s, SKINNY_ALERT); + transmit_tone(s, SKINNY_ALERT, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid); transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid); transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */ @@ -2754,7 +2765,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s } return -1; case -1: - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); break; case AST_CONTROL_HOLD: ast_moh_start(ast, data, l->mohinterpret); @@ -2885,14 +2896,14 @@ static int skinny_hold(struct skinny_subchannel *sub) if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE))) return 0; - req->data.closereceivechannel.conferenceId = htolel(0); + req->data.closereceivechannel.conferenceId = htolel(sub->callid); req->data.closereceivechannel.partyId = htolel(sub->callid); transmit_response(s, req); if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE))) return 0; - req->data.stopmedia.conferenceId = htolel(0); + req->data.stopmedia.conferenceId = htolel(sub->callid); req->data.stopmedia.passThruPartyId = htolel(sub->callid); transmit_response(s, req); @@ -3110,12 +3121,12 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT); if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) { - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); } ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten)); if (ast_pthread_create(&t, NULL, skinny_newcall, c)) { @@ -3149,12 +3160,12 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT); if (!ast_ignore_pattern(c->context, sd->exten)) { - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); } if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) { if (!ast_matchmore_extension(c, c->context, sd->exten, 1, l->cid_num)) { @@ -3257,7 +3268,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession /* We're answering a ringing call */ ast_queue_control(sub->owner, AST_CONTROL_ANSWER); transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid); transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED); @@ -3273,8 +3284,8 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK); /* start the switch thread */ @@ -3333,7 +3344,7 @@ static int handle_offhook_message(struct skinny_req *req, struct skinnysession * /* We're answering a ringing call */ ast_queue_control(sub->owner, AST_CONTROL_ANSWER); transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED); start_rtp(sub); @@ -3348,8 +3359,8 @@ static int handle_offhook_message(struct skinny_req *req, struct skinnysession * transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK); /* start the switch thread */ @@ -3737,7 +3748,7 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc if (skinnydebug) ast_verbose("Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms); - req->data.startmedia.conferenceId = htolel(0); + req->data.startmedia.conferenceId = htolel(sub->callid); req->data.startmedia.passThruPartyId = htolel(sub->callid); req->data.startmedia.remoteIp = htolel(d->ourip.s_addr); req->data.startmedia.remotePort = htolel(ntohs(us.sin_port)); @@ -3785,11 +3796,11 @@ static int handle_enbloc_call_message(struct skinny_req *req, struct skinnysessi transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) { - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); } ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten)); if (ast_pthread_create(&t, NULL, skinny_newcall, c)) { @@ -3889,12 +3900,12 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT); if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) { - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); } ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten)); if (ast_pthread_create(&t, NULL, skinny_newcall, c)) { @@ -3926,8 +3937,8 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse if (skinnydebug) ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name); - transmit_displaymessage(s, NULL); /* clear display */ - transmit_tone(s, SKINNY_DIALTONE); + transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */ + transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK); /* start the switch thread */ @@ -4048,7 +4059,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse /* We're answering a ringing call */ ast_queue_control(sub->owner, AST_CONTROL_ANSWER); transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid); - transmit_tone(s, SKINNY_SILENCE); + transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid); transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid); transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED); start_rtp(sub);