mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +00:00 
			
		
		
		
	Merge "res_pjsip: Add DTMF INFO Failback mode"
This commit is contained in:
		
							
								
								
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -40,6 +40,10 @@ res_pjsip | |||||||
|    whether to notify dialog-info state 'early' or 'confirmed' on Ringing |    whether to notify dialog-info state 'early' or 'confirmed' on Ringing | ||||||
|    when already INUSE. |    when already INUSE. | ||||||
|  |  | ||||||
|  |  * The endpoint option 'dtmf_mode' has a new option 'auto_dtmf' added. This | ||||||
|  |    mode works similar to 'auto' except uses DTMF INFO as fallback instead of | ||||||
|  |    INBAND. | ||||||
|  |  | ||||||
| res_agi | res_agi | ||||||
| ------------------ | ------------------ | ||||||
|  * The EAGI() application will now look for a dialplan variable named |  * The EAGI() application will now look for a dialplan variable named | ||||||
|   | |||||||
| @@ -1960,6 +1960,12 @@ static int chan_pjsip_digit_begin(struct ast_channel *chan, char digit) | |||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		ast_rtp_instance_dtmf_begin(media->rtp, digit); | ||||||
|  | 		break; | ||||||
|  | 	case AST_SIP_DTMF_AUTO_INFO: | ||||||
|  | 		if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_NONE)) { | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
| 		ast_rtp_instance_dtmf_begin(media->rtp, digit); | 		ast_rtp_instance_dtmf_begin(media->rtp, digit); | ||||||
| 		break; | 		break; | ||||||
| 	case AST_SIP_DTMF_NONE: | 	case AST_SIP_DTMF_NONE: | ||||||
| @@ -2063,6 +2069,20 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in | |||||||
| 	media = channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]; | 	media = channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]; | ||||||
|  |  | ||||||
| 	switch (channel->session->endpoint->dtmf) { | 	switch (channel->session->endpoint->dtmf) { | ||||||
|  | 	case AST_SIP_DTMF_AUTO_INFO: | ||||||
|  | 	{ | ||||||
|  | 		if (!media || !media->rtp) { | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		if (ast_rtp_instance_dtmf_mode_get(media->rtp) != AST_RTP_DTMF_MODE_NONE) { | ||||||
|  | 			ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 negotiated so using it.\n", ast_channel_name(ast)); | ||||||
|  | 			ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		/* If RFC_4733 was not negotiated, fail through to the DTMF_INFO processing */ | ||||||
|  | 		ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 NOT negotiated using INFO instead.\n", ast_channel_name(ast)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	case AST_SIP_DTMF_INFO: | 	case AST_SIP_DTMF_INFO: | ||||||
| 	{ | 	{ | ||||||
| 		struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration); | 		struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration); | ||||||
| @@ -2095,14 +2115,15 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration); | 		ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration); | ||||||
|                 break; | 		break; | ||||||
|         case AST_SIP_DTMF_AUTO: | 	case AST_SIP_DTMF_AUTO: | ||||||
|                 if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) { | 		if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) { | ||||||
|                         return -1; | 			 return -1; | ||||||
|                 } | 		} | ||||||
|  |  | ||||||
|  | 		ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration); | ||||||
|  | 		break; | ||||||
|  |  | ||||||
|                 ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration); |  | ||||||
|                 break; |  | ||||||
|  |  | ||||||
| 	case AST_SIP_DTMF_NONE: | 	case AST_SIP_DTMF_NONE: | ||||||
| 		break; | 		break; | ||||||
|   | |||||||
| @@ -0,0 +1,57 @@ | |||||||
|  | """Add auto_info to endpoint dtmf_mode | ||||||
|  |  | ||||||
|  | Revision ID: 164abbd708c | ||||||
|  | Revises: 86bb1efa278d | ||||||
|  | Create Date: 2017-06-19 13:55:15.354706 | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | # revision identifiers, used by Alembic. | ||||||
|  | revision = '164abbd708c' | ||||||
|  | down_revision = '86bb1efa278d' | ||||||
|  |  | ||||||
|  | from alembic import op | ||||||
|  | import sqlalchemy as sa | ||||||
|  |  | ||||||
|  | OLD_ENUM = ['rfc4733', 'inband', 'info', 'auto'] | ||||||
|  | NEW_ENUM = ['rfc4733', 'inband', 'info', 'auto', 'auto_info'] | ||||||
|  |  | ||||||
|  | old_type = sa.Enum(*OLD_ENUM, name='pjsip_dtmf_mode_values_v2') | ||||||
|  | new_type = sa.Enum(*NEW_ENUM, name='pjsip_dtmf_mode_values_v3') | ||||||
|  |  | ||||||
|  | def upgrade(): | ||||||
|  |     context = op.get_context() | ||||||
|  |  | ||||||
|  |     # Upgrading to this revision WILL clear your directmedia values. | ||||||
|  |     if context.bind.dialect.name != 'postgresql': | ||||||
|  |         op.alter_column('ps_endpoints', 'dtmf_mode', | ||||||
|  |                         type_=new_type, | ||||||
|  |                         existing_type=old_type) | ||||||
|  |     else: | ||||||
|  |         enum = ENUM('rfc4733', 'inband', 'info', 'auto', 'auto_info', | ||||||
|  |                     name='pjsip_dtmf_mode_values_v3') | ||||||
|  |         enum.create(op.get_bind(), checkfirst=False) | ||||||
|  |  | ||||||
|  |         op.execute('ALTER TABLE ps_endpoints ALTER COLUMN dtmf_mode TYPE' | ||||||
|  |                    ' pjsip_dtmf_mode_values_v3 USING' | ||||||
|  |                    ' dtmf_mode::text::pjsip_dtmf_mode_values_v3') | ||||||
|  |  | ||||||
|  |         ENUM(name="pjsip_dtmf_mode_values_v2").drop(op.get_bind(), checkfirst=False) | ||||||
|  |  | ||||||
|  | def downgrade(): | ||||||
|  |     context = op.get_context() | ||||||
|  |  | ||||||
|  |     if context.bind.dialect.name != 'postgresql': | ||||||
|  |         op.alter_column('ps_endpoints', 'dtmf_mode', | ||||||
|  |                         type_=old_type, | ||||||
|  |                         existing_type=new_type) | ||||||
|  |     else: | ||||||
|  |         enum = ENUM('rfc4733', 'inband', 'info', 'auto', | ||||||
|  |                     name='pjsip_dtmf_mode_values_v2') | ||||||
|  |         enum.create(op.get_bind(), checkfirst=False) | ||||||
|  |  | ||||||
|  |         op.execute('ALTER TABLE ps_endpoints ALTER COLUMN dtmf_mode TYPE' | ||||||
|  |                    ' pjsip_dtmf_mode_values USING' | ||||||
|  |                    ' dtmf_mode::text::pjsip_dtmf_mode_values_v2') | ||||||
|  |  | ||||||
|  |         ENUM(name="pjsip_dtmf_mode_values_v3").drop(op.get_bind(), checkfirst=False) | ||||||
| @@ -365,6 +365,8 @@ enum ast_sip_dtmf_mode { | |||||||
| 	AST_SIP_DTMF_INFO, | 	AST_SIP_DTMF_INFO, | ||||||
| 	/*! Use SIP 4733 if supported by the other side or INBAND if not */ | 	/*! Use SIP 4733 if supported by the other side or INBAND if not */ | ||||||
| 	AST_SIP_DTMF_AUTO, | 	AST_SIP_DTMF_AUTO, | ||||||
|  | 	/*! Use SIP 4733 if supported by the other side or INFO DTMF (blech) if not */ | ||||||
|  | 	AST_SIP_DTMF_AUTO_INFO, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|   | |||||||
| @@ -229,6 +229,9 @@ | |||||||
| 							<enum name="auto"> | 							<enum name="auto"> | ||||||
| 								<para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para> | 								<para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para> | ||||||
| 							</enum> | 							</enum> | ||||||
|  | 							<enum name="auto_info"> | ||||||
|  | 								<para>DTMF is sent as RFC 4733 if the other side supports it or as SIP INFO if not.</para> | ||||||
|  | 							</enum> | ||||||
| 						</enumlist> | 						</enumlist> | ||||||
| 					</description> | 					</description> | ||||||
| 				</configOption> | 				</configOption> | ||||||
|   | |||||||
| @@ -371,6 +371,8 @@ static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, | |||||||
| 		endpoint->dtmf = AST_SIP_DTMF_RFC_4733; | 		endpoint->dtmf = AST_SIP_DTMF_RFC_4733; | ||||||
| 	} else if (!strcasecmp(var->value, "inband")) { | 	} else if (!strcasecmp(var->value, "inband")) { | ||||||
| 		endpoint->dtmf = AST_SIP_DTMF_INBAND; | 		endpoint->dtmf = AST_SIP_DTMF_INBAND; | ||||||
|  | 	} else if (!strcasecmp(var->value, "auto_info")) { | ||||||
|  | 		endpoint->dtmf = AST_SIP_DTMF_AUTO_INFO; | ||||||
| 	} else if (!strcasecmp(var->value, "info")) { | 	} else if (!strcasecmp(var->value, "info")) { | ||||||
| 		endpoint->dtmf = AST_SIP_DTMF_INFO; | 		endpoint->dtmf = AST_SIP_DTMF_INFO; | ||||||
| 	} else if (!strcasecmp(var->value, "auto")) { | 	} else if (!strcasecmp(var->value, "auto")) { | ||||||
| @@ -395,8 +397,11 @@ static int dtmf_to_str(const void *obj, const intptr_t *args, char **buf) | |||||||
| 		*buf = "inband"; break; | 		*buf = "inband"; break; | ||||||
| 	case AST_SIP_DTMF_INFO : | 	case AST_SIP_DTMF_INFO : | ||||||
| 		*buf = "info"; break; | 		*buf = "info"; break; | ||||||
|        case AST_SIP_DTMF_AUTO : | 	case AST_SIP_DTMF_AUTO : | ||||||
| 		*buf = "auto"; break; | 		*buf = "auto"; break; | ||||||
|  | 	case AST_SIP_DTMF_AUTO_INFO : | ||||||
|  | 		*buf = "auto_info"; | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		*buf = "none"; | 		*buf = "none"; | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -207,7 +207,7 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me | |||||||
| 		ice->stop(session_media->rtp); | 		ice->stop(session_media->rtp); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) { | 	if (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) { | ||||||
| 		ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833); | 		ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833); | ||||||
| 		ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_DTMF, 1); | 		ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_DTMF, 1); | ||||||
| 	} else if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) { | 	} else if (session->endpoint->dtmf == AST_SIP_DTMF_INBAND) { | ||||||
| @@ -230,7 +230,7 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me | |||||||
| } | } | ||||||
|  |  | ||||||
| static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs, | static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs, | ||||||
|        struct ast_sip_session_media *session_media) | 	struct ast_sip_session_media *session_media) | ||||||
| { | { | ||||||
| 	pjmedia_sdp_attr *attr; | 	pjmedia_sdp_attr *attr; | ||||||
| 	pjmedia_sdp_rtpmap *rtpmap; | 	pjmedia_sdp_rtpmap *rtpmap; | ||||||
| @@ -296,6 +296,16 @@ static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp | |||||||
| 	if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) { | 	if (!tel_event && (session->endpoint->dtmf == AST_SIP_DTMF_AUTO)) { | ||||||
| 		ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND); | 		ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_INBAND); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) { | ||||||
|  | 		if  (tel_event) { | ||||||
|  | 			ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_RFC2833); | ||||||
|  | 		} else { | ||||||
|  | 			ast_rtp_instance_dtmf_mode_set(session_media->rtp, AST_RTP_DTMF_MODE_NONE); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| 	/* Get the packetization, if it exists */ | 	/* Get the packetization, if it exists */ | ||||||
| 	if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) { | 	if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) { | ||||||
| 		unsigned long framing = pj_strtoul(pj_strltrim(&attr->value)); | 		unsigned long framing = pj_strtoul(pj_strltrim(&attr->value)); | ||||||
| @@ -404,7 +414,8 @@ static int set_caps(struct ast_sip_session *session, | |||||||
| 			ast_set_read_format(session->channel, ast_channel_readformat(session->channel)); | 			ast_set_read_format(session->channel, ast_channel_readformat(session->channel)); | ||||||
| 			ast_set_write_format(session->channel, ast_channel_writeformat(session->channel)); | 			ast_set_write_format(session->channel, ast_channel_writeformat(session->channel)); | ||||||
| 		} | 		} | ||||||
| 		if ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) |  | ||||||
|  | 		if ( ((session->endpoint->dtmf == AST_SIP_DTMF_AUTO) || (session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) ) | ||||||
| 		    && (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833) | 		    && (ast_rtp_instance_dtmf_mode_get(session_media->rtp) == AST_RTP_DTMF_MODE_RFC2833) | ||||||
| 		    && (session->dsp)) { | 		    && (session->dsp)) { | ||||||
| 			dsp_features = ast_dsp_get_features(session->dsp); | 			dsp_features = ast_dsp_get_features(session->dsp); | ||||||
| @@ -1136,7 +1147,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as | |||||||
| 	pj_str_t stmp; | 	pj_str_t stmp; | ||||||
| 	pjmedia_sdp_attr *attr; | 	pjmedia_sdp_attr *attr; | ||||||
| 	int index = 0; | 	int index = 0; | ||||||
| 	int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO) ? AST_RTP_DTMF : 0; | 	int noncodec = (session->endpoint->dtmf == AST_SIP_DTMF_RFC_4733 || session->endpoint->dtmf == AST_SIP_DTMF_AUTO || session->endpoint->dtmf == AST_SIP_DTMF_AUTO_INFO) ? AST_RTP_DTMF : 0; | ||||||
| 	int min_packet_size = 0, max_packet_size = 0; | 	int min_packet_size = 0, max_packet_size = 0; | ||||||
| 	int rtp_code; | 	int rtp_code; | ||||||
| 	RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); | 	RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user