[svn-commits] kpfleming: branch kpfleming/sdp-parsing-unbreakage r229637 - /team/kpfleming/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Nov 12 07:25:49 CST 2009


Author: kpfleming
Date: Thu Nov 12 07:25:45 2009
New Revision: 229637

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=229637
Log:
restructure session state change logic so it actually works

convert sendonly magic numbers to enum

more coding guidelines fixes


Modified:
    team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c

Modified: team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c?view=diff&rev=229637&r1=229636&r2=229637
==============================================================================
--- team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c (original)
+++ team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c Thu Nov 12 07:25:45 2009
@@ -1803,6 +1803,13 @@
 static int sip_sipredirect(struct sip_pvt *p, const char *dest);
 
 /*--- Codec handling / SDP */
+enum media_session_mode {
+	MEDIA_SENDRECV = 0,
+	MEDIA_SENDONLY,
+	MEDIA_RECVONLY,
+	MEDIA_INACTIVE,
+};
+
 static void try_suggested_sip_codec(struct sip_pvt *p);
 static const char *get_sdp_iterate(int* start, struct sip_request *req, const char *name);
 static char get_sdp_line(int *start, int stop, struct sip_request *req, const char **value);
@@ -1810,7 +1817,7 @@
 static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action);
 static int process_sdp_o(const char *o, struct sip_pvt *p);
 static int process_sdp_c(const char *c, struct ast_hostent *hp);
-static int process_sdp_a_sendonly(const char *a, int *sendonly);
+static int process_sdp_a_mode(const char *a, enum media_session_mode *mode);
 static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp *newaudiortp, int *last_rtpmap_codec);
 static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp *newvideortp, int *last_rtpmap_codec);
 static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp *newtextrtp, int *last_rtpmap_codec);
@@ -6836,9 +6843,9 @@
 	/* We only want the m and c lines for audio */
 	for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) {
 		if ((media == SDP_AUDIO && ((sscanf(m, "audio %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-		    (sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
-			(media == SDP_VIDEO && ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
-		    (sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
+					    (sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0))) ||
+		    (media == SDP_VIDEO && ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
+					    (sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len > 0)))) {
 			/* See if there's a c= line for this media stream.
 			 * XXX There is no guarantee that we'll be grabbing the c= line for this
 			 * particular media stream here. However, this is the same logic used in process_sdp.
@@ -6915,8 +6922,8 @@
 	int codec;
 
 	/* Others */
-	int sendonly = -1;
-	int vsendonly = -1;
+	enum media_session_mode amode = MEDIA_SENDRECV;
+	enum media_session_mode vmode = MEDIA_SENDRECV;
 	int numberofports;
 	int numberofmediastreams = 0;
 	int last_rtpmap_codec = 0;
@@ -6992,9 +6999,9 @@
 			}
 			break;
 		case 'a':
-			if (process_sdp_a_sendonly(value, &sendonly)) {
+			if (process_sdp_a_mode(value, &amode)) {
 				processed = TRUE;
-				vsendonly = sendonly;
+				vmode = amode;
 			} else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) {
 				processed = TRUE;
 			} else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) {
@@ -7101,18 +7108,6 @@
 
 			if (p->t38.state != T38_ENABLED) {
 				memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms));
-
-				/* KPF: these state changes should not occur until we decide whether
-				   we are actually going to accept this offer or not
-				*/
-				/* Remote party offers T38, we need to update state */
-				if ((t38action == SDP_T38_ACCEPT) &&
-				    (p->t38.state == T38_LOCAL_REINVITE)) {
-					change_t38_state(p, T38_ENABLED);
-				} else if ((t38action == SDP_T38_INITIATE) &&
-					   p->owner && p->lastinvite) {
-					change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */
-				}
 			}
 		} else {
 			ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m);
@@ -7154,13 +7149,13 @@
 				break;
 			case 'a':
 				if (audio) {
-					if (process_sdp_a_sendonly(value, &sendonly)) {
+					if (process_sdp_a_mode(value, &amode)) {
 						processed = TRUE;
 					} else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) {
 						processed = TRUE;
 					}
 				} else if (video) {
-					if (process_sdp_a_sendonly(value, &vsendonly)) {
+					if (process_sdp_a_mode(value, &vmode)) {
 						processed = TRUE;
 					} else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) {
 						processed = TRUE;
@@ -7187,7 +7182,7 @@
 	}
 
 	/* Sanity checks */
-	if (aportno == -1 && vportno == -1 && iportno == -1  && tportno == -1) {
+	if (aportno == -1 && vportno == -1 && iportno == -1 && tportno == -1) {
 		/* No acceptable offer found in SDP  - we have no ports */
 		/* Do not change RTP or VRTP if this is a re-invite */
 		return -2;
@@ -7196,10 +7191,6 @@
 	if (numberofmediastreams > 3) {
 		/* We have too many fax, audio and/or video and/or text media streams, fail this offer */
 		return -3;
-	}
-
-	if (iportno == -1) {
-		change_t38_state(p, T38_DISABLED);
 	}
 
 	/* Now gather all of the codecs that we are asked for: */
@@ -7227,47 +7218,17 @@
 			    ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, apeernoncodeccapability, 0, 0),
 			    ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0));
 	}
-	if (!newjointcapability) {
-		/* If T.38 was not negotiated either, totally bail out... */
-		if ((p->t38.state == T38_DISABLED) || !iportno) {
-			ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
-			/* Do NOT Change current setting */
-			return -1;
-		} else {
-			ast_debug(3, "Have T.38 but no audio codecs, accepting offer anyway\n");
-			/* KPF: except we don't actually finish processing the offer, so the call is broken */
-			return 0;
-		}
-	}
-
-	/* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since
-		they are acceptable */
-	p->jointcapability = newjointcapability;	        /* Our joint codec profile for this call */
-	p->peercapability = newpeercapability;		        /* The other sides capability in latest offer */
-	p->jointnoncodeccapability = newnoncodeccapability;	/* DTMF capabilities */
-
-	ast_rtp_pt_copy(p->rtp, newaudiortp);
-	if (p->vrtp)
-		ast_rtp_pt_copy(p->vrtp, newvideortp);
-	if (p->trtp)
-		ast_rtp_pt_copy(p->trtp, newtextrtp);
-
-	if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
-		ast_clear_flag(&p->flags[0], SIP_DTMF);
-		if (newnoncodeccapability & AST_RTP_DTMF) {
-			/* XXX Would it be reasonable to drop the DSP at this point? XXX */
-			ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833);
-			/* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */
-			ast_rtp_setdtmf(p->rtp, 1);
-			ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
-		} else {
-			ast_set_flag(&p->flags[0], SIP_DTMF_INBAND);
-		}
-	}
-
+
+	if (!newjointcapability && (aportno != -1)) {
+		ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
+		return -1;
+	}
+
+	/* We are now ready to change the sip session with the offered codecs, since
+	   they are acceptable */
 	/* Setup audio address and port */
 	if (p->rtp) {
-		if (aportno > 0) {
+		if (aportno != -1) {
 			struct sockaddr_in sin;
 
 			sin.sin_family = AF_INET;
@@ -7277,6 +7238,23 @@
 			if (debug) {
 				ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
 			}
+			p->jointcapability = newjointcapability;	        /* Our joint codec profile for this call */
+			p->peercapability = newpeercapability;		        /* The other sides capability in latest offer */
+			p->jointnoncodeccapability = newnoncodeccapability;	/* DTMF capabilities */
+
+			ast_rtp_pt_copy(p->rtp, newaudiortp);
+			if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
+				ast_clear_flag(&p->flags[0], SIP_DTMF);
+				if (newnoncodeccapability & AST_RTP_DTMF) {
+					/* XXX Would it be reasonable to drop the DSP at this point? XXX */
+					ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833);
+					/* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */
+					ast_rtp_setdtmf(p->rtp, 1);
+					ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+				} else {
+					ast_set_flag(&p->flags[0], SIP_DTMF_INBAND);
+				}
+			}
 		} else {
 			ast_rtp_stop(p->rtp);
 			if (debug) {
@@ -7284,10 +7262,9 @@
 			}
 		}
 	}
-
 	/* Setup video address and port */
 	if (p->vrtp) {
-		if (vportno > 0) {
+		if (vportno != -1) {
 			struct sockaddr_in sin;
 
 			sin.sin_family = AF_INET;
@@ -7297,6 +7274,7 @@
 			if (debug) {
 				ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
 			}
+			ast_rtp_pt_copy(p->vrtp, newvideortp);
 		} else {
 			ast_rtp_stop(p->vrtp);
 			if (debug) {
@@ -7304,10 +7282,9 @@
 			}
 		}
 	}
-
 	/* Setup text address and port */
 	if (p->trtp) {
-		if (tportno > 0) {
+		if (tportno != -1) {
 			struct sockaddr_in sin;
 
 			sin.sin_family = AF_INET;
@@ -7317,6 +7294,7 @@
 			if (debug) {
 				ast_verbose("Peer T.140 RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
 			}
+			ast_rtp_pt_copy(p->trtp, newtextrtp);
 		} else {
 			ast_rtp_stop(p->trtp);
 			if (debug) {
@@ -7326,13 +7304,14 @@
 	}
 	/* Setup image address and port */
 	if (p->udptl) {
-		if (iportno > 0) {
+		if (iportno != -1) {
 			struct sockaddr_in sin;
 
 			sin.sin_family = AF_INET;
 			sin.sin_port = htons(iportno);
 			if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
 				struct sockaddr_in remote_address = { 0, };
+
 				ast_rtp_get_peer(p->rtp, &remote_address);
 				if (remote_address.sin_addr.s_addr) {
 					memcpy(&sin, &remote_address, sizeof(sin));
@@ -7345,12 +7324,26 @@
 			if (debug) {
 				ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
 			}
+			/* Remote party offers T38, we need to update state */
+			if ((t38action == SDP_T38_ACCEPT) &&
+			    (p->t38.state == T38_LOCAL_REINVITE)) {
+				change_t38_state(p, T38_ENABLED);
+			} else if ((t38action == SDP_T38_INITIATE) &&
+				   p->owner && p->lastinvite) {
+				change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */
+			}
 		} else {
+			change_t38_state(p, T38_DISABLED);
 			ast_udptl_stop(p->udptl);
 			if (debug) {
 				ast_debug(1, "Peer doesn't want T.38 UDPTL\n");
 			}
 		}
+	}
+
+	if ((aportno == -1) && (p->t38.state != T38_DISABLED)) {
+		ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n");
+		return 0;
 	}
 
 	/* Ok, we're going with this offer */
@@ -7375,7 +7368,7 @@
 		ast_set_write_format(p->owner, p->owner->writeformat);
 	}
 	
-	if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && ahp && ahp->h_addr && (!sendonly || sendonly == -1)) {
+	if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && ahp && ahp->h_addr && (amode == MEDIA_SENDRECV)) {
 		ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
 		/* Activate a re-invite */
 		ast_queue_frame(p->owner, &ast_null_frame);
@@ -7393,13 +7386,13 @@
 			sip_peer_hold(p, FALSE);
 		}
 		ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
-	} else if ((ahp && !ahp->h_addr) || (sendonly && sendonly != -1)) {
+	} else if ((ahp && !ahp->h_addr) || (amode != MEDIA_SENDRECV)) {
 		int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD);
 
 		ast_queue_control_data(p->owner, AST_CONTROL_HOLD, 
 				       S_OR(p->mohsuggest, NULL),
 				       !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-		if (sendonly) {
+		if (amode != MEDIA_SENDRECV) {
 			ast_rtp_stop(p->rtp);
 		}
 		/* RTCP needs to go ahead, even if we're on hold!!! */
@@ -7415,10 +7408,10 @@
 				      p->owner->name, 
 				      p->owner->uniqueid);
 		}
-		if (sendonly == 1) {
+		if (amode == MEDIA_SENDONLY) {
 			/* One directional hold (sendonly/recvonly) */
 			ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR);
-		} else if (sendonly == 2) {
+		} else if (amode == MEDIA_INACTIVE) {
 			/* Inactive stream */
 			ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE);
 		} else {
@@ -7530,24 +7523,19 @@
 	return FALSE;
 }
 
-static int process_sdp_a_sendonly(const char *a, int *sendonly)
-{
-	int found = FALSE;
-
+static int process_sdp_a_mode(const char *a, enum media_session_mode *mode)
+{
 	if (!strcasecmp(a, "sendonly")) {
-		if (*sendonly == -1)
-			*sendonly = 1;
-		found = TRUE;
+		*mode = MEDIA_SENDONLY;
+		return TRUE;
 	} else if (!strcasecmp(a, "inactive")) {
-		if (*sendonly == -1)
-			*sendonly = 2;
-		found = TRUE;
+		*mode = MEDIA_INACTIVE;
+		return TRUE;
 	}  else if (!strcasecmp(a, "sendrecv")) {
-		if (*sendonly == -1)
-			*sendonly = 0;
-		found = TRUE;
-	}
-	return found;
+		*mode = MEDIA_SENDRECV;
+		return TRUE;
+	}
+	return FALSE;
 }
 
 static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp *newaudiortp, int *last_rtpmap_codec)
@@ -7574,10 +7562,13 @@
 			int format = 0;
 			for (codec_n = 0; codec_n < MAX_RTP_PT; codec_n++) {
 				format = ast_rtp_codec_getformat(codec_n);
-				if (!format)	/* non-codec or not found */
+				if (!format) {
+					/* non-codec or not found */
 					continue;
-				if (option_debug)
+				}
+				if (option_debug) {
 					ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing);
+				}
 				ast_codec_pref_setsize(pref, format, framing);
 			}
 			ast_rtp_codec_setpref(p->rtp, pref);
@@ -7588,19 +7579,20 @@
 		if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) {
 			if (ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype,
 			    ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0) != -1) {
-				if (debug)
+				if (debug) {
 					ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec);
+				}
 				//found_rtpmap_codecs[last_rtpmap_codec] = codec;
 				(*last_rtpmap_codec)++;
 				found = TRUE;
 			} else {
 				ast_rtp_unset_m_type(newaudiortp, codec);
-				if (debug)
+				if (debug) {
 					ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec);
+				}
 			}
-		} else {
-			if (debug)
-				ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
+		} else if (debug) {
+			ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
 		}
 	}
 
@@ -7620,20 +7612,21 @@
 			/* Note: should really look at the '#chans' params too */
 			if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) {
 				if (ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0) != -1) {
-					if (debug)
+					if (debug) {
 						ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec);
+					}
 					//found_rtpmap_codecs[last_rtpmap_codec] = codec;
 					(*last_rtpmap_codec)++;
 					found = TRUE;
 				} else {
 					ast_rtp_unset_m_type(newvideortp, codec);
-					if (debug) 
+					if (debug) {
 						ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec);
+					}
 				}
 			}
-		} else {
-			if (debug)
-				ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
+		} else if (debug) {
+			ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
 		}
 	}
 
@@ -7657,9 +7650,8 @@
 					found = TRUE;
 				}
 			}
-		} else {
-			if (debug)
-				ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
+		} else if (debug) {
+			ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
 		}
 	}
 
@@ -7673,7 +7665,7 @@
 	int x;
 
 	if ((sscanf(a, "T38FaxMaxBuffer:%30d", &x) == 1)) {
-		ast_debug(3, "MaxBufferSize:%d\n", x);
+		ast_debug(3, "MaxBufferSize: %d\n", x);
 		found = TRUE;
 	} else if ((sscanf(a, "T38MaxBitRate:%30d", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30d", &x) == 1)) {
 		ast_debug(3, "T38MaxBitRate: %d\n", x);




More information about the svn-commits mailing list