Parcourir la source

nathelper: added support for SDP rtcp attribute (RFC 3605)

Alfred E. Heggestad il y a 17 ans
Parent
commit
788c80f1f3
1 fichiers modifiés avec 81 ajouts et 0 suppressions
  1. 81 0
      modules_s/nathelper/nathelper.c

+ 81 - 0
modules_s/nathelper/nathelper.c

@@ -1130,6 +1130,31 @@ extract_mediainfo(str *body, str *mediaport, str *payload_types)
 	return -1;
 }
 
+static int
+extract_rtcp(str *body, str *rtcpport)
+{
+	char *cp, *cp1;
+	int len;
+
+	cp1 = NULL;
+	for (cp = body->s; (len = body->s + body->len - cp) > 0;) {
+		cp1 = ser_memmem(cp, "a=rtcp:", len, 7);
+		if (cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
+			break;
+		cp = cp1 + 7;
+	}
+
+	if (cp1 == NULL)
+		return -1;
+
+	rtcpport->s = cp1 + 7; /* skip `a=rtcp:' */
+	rtcpport->len = eat_line(rtcpport->s, body->s + body->len -
+				 rtcpport->s) - rtcpport->s;
+	trim_len(rtcpport->len, rtcpport->s, *rtcpport);
+
+	return 0;
+}
+
 static int
 alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
   str *newip, int newpf, int preserve)
@@ -1320,6 +1345,40 @@ alter_mediaport(struct sip_msg *msg, str *body, str *oldport, str *newport,
 	return 0;
 }
 
+static int
+alter_rtcp(struct sip_msg *msg, str *body, str *oldport, str *newport)
+{
+	char *buf;
+	int offset;
+	struct lump* anchor;
+
+	/* check that updating rtcpport is really necessary */
+	if (newport->len == oldport->len &&
+	    memcmp(newport->s, oldport->s, newport->len) == 0)
+		return 0;
+
+	buf = pkg_malloc(newport->len);
+	if (buf == NULL) {
+		LOG(L_ERR, "ERROR: alter_rtcp: out of memory\n");
+		return -1;
+	}
+	offset = oldport->s - msg->buf;
+	anchor = del_lump(msg, offset, oldport->len, 0);
+	if (anchor == NULL) {
+		LOG(L_ERR, "ERROR: alter_rtcp: del_lump failed\n");
+		pkg_free(buf);
+		return -1;
+	}
+	memcpy(buf, newport->s, newport->len);
+	if (insert_new_lump_after(anchor, buf, newport->len, 0) == 0) {
+		LOG(L_ERR, "ERROR: alter_rtcp: insert_new_lump_after failed\n");
+		pkg_free(buf);
+		return -1;
+	}
+
+	return 0;
+}
+
 static char *
 gencookie()
 {
@@ -1862,6 +1921,7 @@ force_rtp_proxy(struct sip_msg *msg, char *param1, char *param2, int offer)
 {
 	str body, body1, oldport, oldip, newport, newip, str1, str2, s;
 	str callid, from_tag, to_tag, tmp, c1_oldip, payload_types;
+	str oldrtcp, newrtcp;
 	int create, port, len, asymmetric, flookup, argc, proxied, real, i;
 	int oidx, pf, pf1, force, c1_pf, rep_oidx;
 	unsigned int node_idx, oldport_i;
@@ -2126,6 +2186,13 @@ force_rtp_proxy(struct sip_msg *msg, char *param1, char *param2, int offer)
 				    " extract media port from the message\n");
 				return -1;
 			}
+			/* Extract rtcp attribute */
+			tmpstr1.s = m1p;
+			tmpstr1.len = m2p - m1p;
+			oldrtcp.s = NULL;
+			oldrtcp.len = 0;
+			extract_rtcp(&tmpstr1, &oldrtcp);
+
 			++medianum;
 			if (asymmetric != 0 || real != 0) {
 				newip = oldip;
@@ -2276,6 +2343,20 @@ force_rtp_proxy(struct sip_msg *msg, char *param1, char *param2, int offer)
 				if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1)
 					return -1;
 			}
+			/*
+			 * Alter RTCP attribute if present. Inserting RTP port + 1 (as allocated
+			 * by RTP proxy). No IP-address is needed in the new RTCP attribute as the
+			 * 'c' attribute (altered below) will contain the RTP proxy IP address.
+			 * See RFC 3605 for definition of RTCP attribute.
+			 */
+			if (oldrtcp.s && oldrtcp.len) {
+				newrtcp.s = int2str(port+1, &newrtcp.len); /* beware static buffer */
+				/* Alter port. */
+				body1.s = m1p;
+				body1.len = bodylimit - body1.s;
+				if (alter_rtcp(msg, &body1, &oldrtcp, &newrtcp) == -1)
+					return -1;
+			}
 			/*
 			 * Alter IP. Don't alter IP common for the session
 			 * more than once, but always alter it even if the IP is present