[asterisk-commits] file: branch file/issue12437 r176549 - /team/file/issue12437/channels/chan_sip.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Feb 17 10:32:17 CST 2009


Author: file
Date: Tue Feb 17 10:32:17 2009
New Revision: 176549

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=176549
Log:
Change how we handle an initial invite with T38 and creation of SDP. If we get an initial INVITE with T38 and audio we will now send back both T38 and audio on the response, not just T38. For outgoing calls originating from a device that has started a call with T38 in the initial INVITE we will no longer setup a call with just T38. Next up is expanding this so that if one side has negotiated T38 and sent us UDPTL we then trigger a reinvite on the other side. Will that be how I finish this off? We'll see... experimentation begins.

Modified:
    team/file/issue12437/channels/chan_sip.c

Modified: team/file/issue12437/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/team/file/issue12437/channels/chan_sip.c?view=diff&rev=176549&r1=176548&r2=176549
==============================================================================
--- team/file/issue12437/channels/chan_sip.c (original)
+++ team/file/issue12437/channels/chan_sip.c Tue Feb 17 10:32:17 2009
@@ -847,7 +847,6 @@
 /*! \brief T38 States for a call */
 enum t38state {
         T38_DISABLED = 0,                /*!< Not enabled */
-        T38_LOCAL_DIRECT,                /*!< Offered from local */
         T38_LOCAL_REINVITE,              /*!< Offered from local - REINVITE */
         T38_PEER_DIRECT,                 /*!< Offered from peer */
         T38_PEER_REINVITE,               /*!< Offered from peer - REINVITE */
@@ -1325,7 +1324,7 @@
 static void add_noncodec_to_sdp(const struct sip_pvt *p, int format, int sample_rate,
 				char **m_buf, size_t *m_size, char **a_buf, size_t *a_size,
 				int debug);
-static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p);
+static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int add_audio, int add_t38);
 static void stop_media_flows(struct sip_pvt *p);
 
 /*--- Authentication stuff */
@@ -3052,12 +3051,7 @@
 		} else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) {
 			/* We're replacing a call. */
 			p->options->replaces = ast_var_value(current);
-		} else if (!strcasecmp(ast_var_name(current), "T38CALL")) {
-			p->t38.state = T38_LOCAL_DIRECT;
-			if (option_debug)
-				ast_log(LOG_DEBUG,"T38State change to %d on channel %s\n", p->t38.state, ast->name);
-		}
-
+		}
 	}
 	
 	res = 0;
@@ -3760,16 +3754,9 @@
 		ast_setstate(ast, AST_STATE_UP);
 		if (option_debug)
 			ast_log(LOG_DEBUG, "SIP answering channel: %s\n", ast->name);
-		if (p->t38.state == T38_PEER_DIRECT) {
-			p->t38.state = T38_ENABLED;
-			if (option_debug > 1)
-				ast_log(LOG_DEBUG,"T38State change to %d on channel %s\n", p->t38.state, ast->name);
-			res = transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
-			ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
-		} else {
-			res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
-			ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
-		}
+
+		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
+		ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
 	}
 	ast_mutex_unlock(&p->lock);
 	return res;
@@ -4221,10 +4208,6 @@
 		pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid);
 	if (i->rtp)
 		ast_jb_configure(tmp, &global_jbconf);
-
-	/* If the INVITE contains T.38 SDP information set the proper channel variable so a created outgoing call will also have T.38 */
-	if (i->udptl && i->t38.state == T38_PEER_DIRECT)
-		pbx_builtin_setvar_helper(tmp, "_T38CALL", "1");
 
 	/* Set channel variables for this call from configuration */
 	for (v = i->chanvars ; v ; v = v->next)
@@ -6511,7 +6494,7 @@
 }
 
 /*! \brief Add T.38 Session Description Protocol message */
-static int add_t38_sdp(struct sip_request *resp, struct sip_pvt *p)
+static attribute_unused int add_t38_sdp(struct sip_request *resp, struct sip_pvt *p)
 {
 	int len = 0;
 	int x = 0;
@@ -6639,7 +6622,7 @@
 #define SDP_SAMPLE_RATE(x) 8000
 
 /*! \brief Add Session Description Protocol message */
-static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p)
+static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int add_audio, int add_t38)
 {
 	int len = 0;
 	int alreadysent = 0;
@@ -6659,26 +6642,35 @@
 	char *hold;
 	char m_audio[256];				/* Media declaration line for audio */
 	char m_video[256];				/* Media declaration line for video */
+	char m_modem[256];                              /* Media declaration line for t38 */
 	char a_audio[1024];				/* Attributes for audio */
 	char a_video[1024];				/* Attributes for video */
+	char a_modem[1024];                             /* Attributes for t38 */
 	char *m_audio_next = m_audio;
 	char *m_video_next = m_video;
+	char *m_modem_next = m_modem;
 	size_t m_audio_left = sizeof(m_audio);
 	size_t m_video_left = sizeof(m_video);
+	size_t m_modem_left = sizeof(m_modem);
 	char *a_audio_next = a_audio;
 	char *a_video_next = a_video;
+	char *a_modem_next = a_modem;
 	size_t a_audio_left = sizeof(a_audio);
 	size_t a_video_left = sizeof(a_video);
+	size_t a_modem_left = sizeof(a_modem);
 
 	int x;
-	int capability;
+	int capability = 0;
 	int needvideo = FALSE;
 	int debug = sip_debug_test_pvt(p);
 	int min_audio_packet_size = 0;
 	int min_video_packet_size = 0;
 
 	m_video[0] = '\0';	/* Reset the video media string if it's not needed */
-
+	m_modem[0] = '\0';
+
+	ast_log(LOG_NOTICE, "add audio = %d add t38 = %d\n", add_audio, add_t38);
+	
 	if (!p->rtp) {
 		ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
 		return AST_FAILURE;
@@ -6705,64 +6697,8 @@
 		dest.sin_port = sin.sin_port;
 	}
 
-	capability = p->jointcapability;
-
-
-	if (option_debug > 1) {
-		char codecbuf[SIPBUFSIZE];
-		ast_log(LOG_DEBUG, "** Our capability: %s Video flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), ast_test_flag(&p->flags[0], SIP_NOVIDEO) ? "True" : "False");
-		ast_log(LOG_DEBUG, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
-	}
-	
-#ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS
-	if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP)) {
-		ast_build_string(&m_audio_next, &m_audio_left, " %d", 191);
-		ast_build_string(&a_audio_next, &a_audio_left, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
-	}
-#endif
-
-	/* Check if we need video in this call */
-	if ((capability & AST_FORMAT_VIDEO_MASK) && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
-		if (p->vrtp) {
-			needvideo = TRUE;
-			if (option_debug > 1)
-				ast_log(LOG_DEBUG, "This call needs video offers!\n");
-		} else if (option_debug > 1)
-			ast_log(LOG_DEBUG, "This call needs video offers, but there's no video support enabled!\n");
-	}
-		
-
-	/* Ok, we need video. Let's add what we need for video and set codecs.
-	   Video is handled differently than audio since we can not transcode. */
-	if (needvideo) {
-		/* Determine video destination */
-		if (p->vredirip.sin_addr.s_addr) {
-			vdest.sin_addr = p->vredirip.sin_addr;
-			vdest.sin_port = p->vredirip.sin_port;
-		} else {
-			vdest.sin_addr = p->ourip;
-			vdest.sin_port = vsin.sin_port;
-		}
-		ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
-
-		/* Build max bitrate string */
-		if (p->maxcallbitrate)
-			snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
-		if (debug) 
-			ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));	
-	}
-
-	if (debug) 
-		ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(sin.sin_port));	
-
-	/* Start building generic SDP headers */
-
-	/* We break with the "recommendation" and send our IP, in order that our
-	   peer doesn't have to ast_gethostbyname() us */
-
-	snprintf(owner, sizeof(owner), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
+        snprintf(owner, sizeof(owner), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
 	snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
-	ast_build_string(&m_audio_next, &m_audio_left, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
 
 	if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
 		hold = "a=recvonly\r\n";
@@ -6771,98 +6707,201 @@
 	else
 		hold = "a=sendrecv\r\n";
 
-	/* Now, start adding audio codecs. These are added in this order:
-		- First what was requested by the calling channel
-		- Then preferences in order from sip.conf device config for this peer/user
-		- Then other codecs in capabilities, including video
-	*/
-
-	/* Prefer the audio codec we were requested to use, first, no matter what 
-		Note that p->prefcodec can include video codecs, so mask them out
-	 */
-	if (capability & p->prefcodec) {
-		int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK;
-
-		add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
-				 &m_audio_next, &m_audio_left,
-				 &a_audio_next, &a_audio_left,
-				 debug, &min_audio_packet_size);
-		alreadysent |= codec;
-	}
-
-	/* Start by sending our preferred audio codecs */
-	for (x = 0; x < 32; x++) {
-		int codec;
-
-		if (!(codec = ast_codec_pref_index(&p->prefs, x)))
-			break; 
-
-		if (!(capability & codec))
-			continue;
-
-		if (alreadysent & codec)
-			continue;
-
-		add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
-				 &m_audio_next, &m_audio_left,
-				 &a_audio_next, &a_audio_left,
-				 debug, &min_audio_packet_size);
-		alreadysent |= codec;
-	}
-
-	/* Now send any other common audio and video codecs, and non-codec formats: */
-	for (x = 1; x <= (needvideo ? AST_FORMAT_MAX_VIDEO : AST_FORMAT_MAX_AUDIO); x <<= 1) {
-		if (!(capability & x))	/* Codec not requested */
-			continue;
-
-		if (alreadysent & x)	/* Already added to SDP */
-			continue;
-
-		if (x <= AST_FORMAT_MAX_AUDIO)
-			add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x),
+	if (add_audio) {
+		capability = p->jointcapability;
+
+
+		if (option_debug > 1) {
+			char codecbuf[SIPBUFSIZE];
+			ast_log(LOG_DEBUG, "** Our capability: %s Video flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), ast_test_flag(&p->flags[0], SIP_NOVIDEO) ? "True" : "False");
+			ast_log(LOG_DEBUG, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
+		}
+
+#ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS
+		if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP)) {
+			ast_build_string(&m_audio_next, &m_audio_left, " %d", 191);
+			ast_build_string(&a_audio_next, &a_audio_left, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
+		}
+#endif
+
+		/* Check if we need video in this call */
+		if ((capability & AST_FORMAT_VIDEO_MASK) && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
+			if (p->vrtp) {
+				needvideo = TRUE;
+				if (option_debug > 1)
+					ast_log(LOG_DEBUG, "This call needs video offers!\n");
+			} else if (option_debug > 1)
+				ast_log(LOG_DEBUG, "This call needs video offers, but there's no video support enabled!\n");
+		}
+
+
+		/* Ok, we need video. Let's add what we need for video and set codecs.
+		   Video is handled differently than audio since we can not transcode. */
+		if (needvideo) {
+			/* Determine video destination */
+			if (p->vredirip.sin_addr.s_addr) {
+				vdest.sin_addr = p->vredirip.sin_addr;
+				vdest.sin_port = p->vredirip.sin_port;
+			} else {
+				vdest.sin_addr = p->ourip;
+				vdest.sin_port = vsin.sin_port;
+			}
+			ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
+
+			/* Build max bitrate string */
+			if (p->maxcallbitrate)
+				snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
+			if (debug) 
+				ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));	
+		}
+
+		if (debug) 
+			ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(sin.sin_port));	
+
+		ast_build_string(&m_audio_next, &m_audio_left, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
+
+		/* Now, start adding audio codecs. These are added in this order:
+		   - First what was requested by the calling channel
+		   - Then preferences in order from sip.conf device config for this peer/user
+		   - Then other codecs in capabilities, including video
+		*/
+
+		/* Prefer the audio codec we were requested to use, first, no matter what 
+		   Note that p->prefcodec can include video codecs, so mask them out
+		*/
+		if (capability & p->prefcodec) {
+			int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK;
+
+			add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
 					 &m_audio_next, &m_audio_left,
 					 &a_audio_next, &a_audio_left,
 					 debug, &min_audio_packet_size);
-		else 
-			add_codec_to_sdp(p, x, 90000,
-					 &m_video_next, &m_video_left,
-					 &a_video_next, &a_video_left,
-					 debug, &min_video_packet_size);
-	}
-
-	/* Now add DTMF RFC2833 telephony-event as a codec */
-	for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
-		if (!(p->jointnoncodeccapability & x))
-			continue;
-
-		add_noncodec_to_sdp(p, x, 8000,
-				    &m_audio_next, &m_audio_left,
-				    &a_audio_next, &a_audio_left,
-				    debug);
-	}
-
-	if (option_debug > 2)
-		ast_log(LOG_DEBUG, "-- Done with adding codecs to SDP\n");
-
-	if (!p->owner || !ast_internal_timing_enabled(p->owner))
-		ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
-
-	if (min_audio_packet_size)
-		ast_build_string(&a_audio_next, &a_audio_left, "a=ptime:%d\r\n", min_audio_packet_size);
-
-	if (min_video_packet_size)
-		ast_build_string(&a_video_next, &a_video_left, "a=ptime:%d\r\n", min_video_packet_size);
-
-	if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0))
-		ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
-
-	ast_build_string(&m_audio_next, &m_audio_left, "\r\n");
-	if (needvideo)
-		ast_build_string(&m_video_next, &m_video_left, "\r\n");
-
-	len = strlen(version) + strlen(subject) + strlen(owner) + strlen(connection) + strlen(stime) + strlen(m_audio) + strlen(a_audio) + strlen(hold);
+			alreadysent |= codec;
+		}
+
+		/* Start by sending our preferred audio codecs */
+		for (x = 0; x < 32; x++) {
+			int codec;
+
+			if (!(codec = ast_codec_pref_index(&p->prefs, x)))
+				break; 
+
+			if (!(capability & codec))
+				continue;
+
+			if (alreadysent & codec)
+				continue;
+
+			add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
+					 &m_audio_next, &m_audio_left,
+					 &a_audio_next, &a_audio_left,
+					 debug, &min_audio_packet_size);
+			alreadysent |= codec;
+		}
+
+		/* Now send any other common audio and video codecs, and non-codec formats: */
+		for (x = 1; x <= (needvideo ? AST_FORMAT_MAX_VIDEO : AST_FORMAT_MAX_AUDIO); x <<= 1) {
+			if (!(capability & x))	/* Codec not requested */
+				continue;
+
+			if (alreadysent & x)	/* Already added to SDP */
+				continue;
+
+			if (x <= AST_FORMAT_MAX_AUDIO)
+				add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x),
+						 &m_audio_next, &m_audio_left,
+						 &a_audio_next, &a_audio_left,
+						 debug, &min_audio_packet_size);
+			else 
+				add_codec_to_sdp(p, x, 90000,
+						 &m_video_next, &m_video_left,
+						 &a_video_next, &a_video_left,
+						 debug, &min_video_packet_size);
+		}
+
+		/* Now add DTMF RFC2833 telephony-event as a codec */
+		for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
+			if (!(p->jointnoncodeccapability & x))
+				continue;
+
+			add_noncodec_to_sdp(p, x, 8000,
+					    &m_audio_next, &m_audio_left,
+					    &a_audio_next, &a_audio_left,
+					    debug);
+		}
+
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "-- Done with adding codecs to SDP\n");
+
+		if (!p->owner || !ast_internal_timing_enabled(p->owner))
+			ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
+
+		if (min_audio_packet_size)
+			ast_build_string(&a_audio_next, &a_audio_left, "a=ptime:%d\r\n", min_audio_packet_size);
+
+		if (min_video_packet_size)
+			ast_build_string(&a_video_next, &a_video_left, "a=ptime:%d\r\n", min_video_packet_size);
+
+		if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0))
+			ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
+
+		ast_build_string(&m_audio_next, &m_audio_left, "\r\n");
+		if (needvideo)
+			ast_build_string(&m_video_next, &m_video_left, "\r\n");
+	}
+
+	if (add_t38 && p->udptl) {
+		struct sockaddr_in udptlsin;
+		struct sockaddr_in udptldest = { 0, };
+
+		ast_udptl_get_us(p->udptl, &udptlsin);
+
+		if (p->udptlredirip.sin_addr.s_addr) {
+			udptldest.sin_port = p->udptlredirip.sin_port;
+			udptldest.sin_addr = p->udptlredirip.sin_addr;
+		} else {
+			udptldest.sin_addr = p->ourip;
+			udptldest.sin_port = udptlsin.sin_port;
+		}
+
+		if (debug) {
+			ast_log(LOG_DEBUG, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(udptlsin.sin_port));
+			ast_log(LOG_DEBUG, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
+				p->t38.capability,
+				p->t38.peercapability,
+				p->t38.jointcapability);
+		}
+
+		ast_build_string(&m_modem_next, &m_modem_left, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
+
+		if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:0\r\n");
+		if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1)
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:1\r\n");
+		if ((x = t38_get_rate(p->t38.jointcapability)))
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38MaxBitRate:%d\r\n",x);
+		if ((p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) == T38FAX_FILL_BIT_REMOVAL)
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxFillBitRemoval\r\n");
+		if ((p->t38.jointcapability & T38FAX_TRANSCODING_MMR) == T38FAX_TRANSCODING_MMR)
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingMMR\r\n");
+		if ((p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) == T38FAX_TRANSCODING_JBIG)
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingJBIG\r\n");
+		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
+		x = ast_udptl_get_local_max_datagram(p->udptl);
+		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxBuffer:%d\r\n",x);
+		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxDatagram:%d\r\n",x);
+		if (p->t38.jointcapability != T38FAX_UDP_EC_NONE)
+			ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC");
+	}
+
+	len = strlen(version) + strlen(subject) + strlen(owner) + strlen(connection) + strlen(stime);
+	if (add_audio)
+		len += strlen(m_audio) + strlen(a_audio) + strlen(hold);
 	if (needvideo) /* only if video response is appropriate */
 		len += strlen(m_video) + strlen(a_video) + strlen(bandwidth) + strlen(hold);
+	if (add_t38) {
+		len += strlen(m_modem) + strlen(a_modem);
+	}
 
 	add_header(resp, "Content-Type", "application/sdp");
 	add_header_contentLength(resp, len);
@@ -6873,13 +6912,19 @@
 	if (needvideo)	 	/* only if video response is appropriate */
 		add_line(resp, bandwidth);
 	add_line(resp, stime);
-	add_line(resp, m_audio);
-	add_line(resp, a_audio);
-	add_line(resp, hold);
+	if (add_audio) {
+		add_line(resp, m_audio);
+		add_line(resp, a_audio);
+		add_line(resp, hold);
+	}
 	if (needvideo) { /* only if video response is appropriate */
 		add_line(resp, m_video);
 		add_line(resp, a_video);
 		add_line(resp, hold);	/* Repeat hold for the video stream */
+	}
+	if (add_t38) {
+		add_line(resp, m_modem);
+		add_line(resp, a_modem);
 	}
 
 	/* Update lastrtprx when we send our SDP */
@@ -6905,8 +6950,7 @@
 	}
 	respprep(&resp, p, msg, req);
 	if (p->udptl) {
-		ast_udptl_offered_from_local(p->udptl, 0);
-		add_t38_sdp(&resp, p);
+		add_sdp(&resp, p, 0, 1);
 	} else 
 		ast_log(LOG_ERROR, "Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid);
 	if (retrans && !p->pendinginvite)
@@ -6949,8 +6993,13 @@
 				ast_log(LOG_DEBUG, "Setting framing from config on incoming call\n");
 			ast_rtp_codec_setpref(p->rtp, &p->prefs);
 		}
-		try_suggested_sip_codec(p);	
-		add_sdp(&resp, p);
+		try_suggested_sip_codec(p);
+		if (p->t38.state == T38_PEER_DIRECT || p->t38.state == T38_ENABLED) {
+			p->t38.state = T38_ENABLED;
+			add_sdp(&resp, p, 1, 1);
+		} else {
+			add_sdp(&resp, p, 1, 0);
+		}
 	} else 
 		ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid);
 	if (reliable && !p->pendinginvite)
@@ -7017,7 +7066,7 @@
 		add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)");
 	if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
 		append_history(p, "ReInv", "Re-invite sent");
-	add_sdp(&req, p);
+	add_sdp(&req, p, 1, 0);
 	/* Use this as the basis */
 	initialize_initreq(p, &req);
 	p->lastinvite = p->ocseq;
@@ -7039,8 +7088,8 @@
 	add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
 	if (sipdebug)
 		add_header(&req, "X-asterisk-info", "SIP re-invite (T38 switchover)");
-	ast_udptl_offered_from_local(p->udptl, 1);
-	add_t38_sdp(&req, p);
+	add_sdp(&req, p, 0, 1);
+
 	/* Use this as the basis */
 	initialize_initreq(p, &req);
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);		/* Change direction of this dialog */
@@ -7366,13 +7415,13 @@
 		ast_channel_unlock(chan);
 	}
 	if (sdp) {
-		if (p->udptl && (p->t38.state == T38_LOCAL_DIRECT || p->t38.state == T38_LOCAL_REINVITE)) {
+		if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
 			ast_udptl_offered_from_local(p->udptl, 1);
 			if (option_debug)
 				ast_log(LOG_DEBUG, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
-			add_t38_sdp(&req, p);
+			add_sdp(&req, p, 0, 1);
 		} else if (p->rtp) 
-			add_sdp(&req, p);
+			add_sdp(&req, p, 1, 0);
 	} else {
 		add_header_contentLength(&req, 0);
 	}
@@ -12530,7 +12579,7 @@
 					ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
 			}
 		}
-		if ((p->t38.state == T38_LOCAL_REINVITE) || (p->t38.state == T38_LOCAL_DIRECT)) {
+		if (p->t38.state == T38_LOCAL_REINVITE) {
 			/* If there was T38 reinvite and we are supposed to answer with 200 OK than this should set us to T38 negotiated mode */
 			p->t38.state = T38_ENABLED;
 			if (option_debug)
@@ -12640,21 +12689,7 @@
 			/* While figuring that out, hangup the call */
 			if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE))
 				ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
-			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
-		} else if (p->udptl && p->t38.state == T38_LOCAL_DIRECT) {
-			/* We tried to send T.38 out in an initial INVITE and the remote side rejected it,
-			   right now we can't fall back to audio so totally abort.
-			*/
-			p->t38.state = T38_DISABLED;
-			/* Try to reset RTP timers */
-			ast_rtp_set_rtptimers_onhold(p->rtp);
-			ast_log(LOG_ERROR, "Got error on T.38 initial invite. Bailing out.\n");
-
-			/* The dialog is now terminated */
-			if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE))
-				ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
 			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
-			sip_alreadygone(p);
 		} else {
 			/* We can't set up this call, so give up */
 			if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE))




More information about the asterisk-commits mailing list