Răsfoiți Sursa

Merge pull request #863 from mslehto/sdpops

modules/sdpops - extend sdp_remove_line_by_prefix()
Daniel-Constantin Mierla 8 ani în urmă
părinte
comite
44a87c1892

+ 13 - 6
modules/app_lua/app_lua_exp.c

@@ -2157,7 +2157,8 @@ static int lua_sr_sdpops_remove_transport(lua_State *L)
 static int lua_sr_sdpops_remove_line_by_prefix(lua_State *L)
 static int lua_sr_sdpops_remove_line_by_prefix(lua_State *L)
 {
 {
 	int ret;
 	int ret;
-	str media;
+	str prefix = STR_NULL;
+	str media = STR_NULL;
 	sr_lua_env_t *env_L;
 	sr_lua_env_t *env_L;
 
 
 	env_L = sr_lua_env_get();
 	env_L = sr_lua_env_get();
@@ -2174,16 +2175,22 @@ static int lua_sr_sdpops_remove_line_by_prefix(lua_State *L)
 		return app_lua_return_error(L);
 		return app_lua_return_error(L);
 	}
 	}
 
 
-	if(lua_gettop(L)!=1)
+	if(lua_gettop(L)==1)
+	{
+		prefix.s = (char *) lua_tostring(L, -1);
+		prefix.len = strlen(prefix.s);
+	} else if(lua_gettop(L)==2)
 	{
 	{
+		prefix.s = (char *) lua_tostring(L, -2);
+		prefix.len = strlen(prefix.s);
+		media.s = (char *) lua_tostring(L, -1);
+		media.len = strlen(media.s);
+	} else {
 		LM_ERR("incorrect number of arguments\n");
 		LM_ERR("incorrect number of arguments\n");
 		return app_lua_return_error(L);
 		return app_lua_return_error(L);
 	}
 	}
 
 
-	media.s = (char*)lua_tostring(L, -1);
-	media.len = strlen(media.s);
-
-	ret = _lua_sdpopsb.sdp_remove_line_by_prefix(env_L->msg, &media);
+	ret = _lua_sdpopsb.sdp_remove_line_by_prefix(env_L->msg, &prefix, &media);
 
 
 	return app_lua_return_int(L, ret);
 	return app_lua_return_int(L, ret);
 }
 }

+ 1 - 1
modules/sdpops/api.h

@@ -41,7 +41,7 @@ typedef struct sdpops_binds {
 	sdp_keep_media_t     sdp_keep_codecs_by_name;
 	sdp_keep_media_t     sdp_keep_codecs_by_name;
 	sdp_remove_media_t   sdp_remove_media;
 	sdp_remove_media_t   sdp_remove_media;
 	sdp_remove_media_t   sdp_remove_transport;
 	sdp_remove_media_t   sdp_remove_transport;
-	sdp_remove_media_t   sdp_remove_line_by_prefix;
+	sdp_remove_media_type_t   sdp_remove_line_by_prefix;
 	sdp_remove_media_type_t   sdp_remove_codecs_by_id;
 	sdp_remove_media_type_t   sdp_remove_codecs_by_id;
 	sdp_remove_media_type_t   sdp_remove_codecs_by_name;
 	sdp_remove_media_type_t   sdp_remove_codecs_by_name;
 } sdpops_api_t;
 } sdpops_api_t;

+ 1 - 1
modules/sdpops/doc/sdpops_admin.xml

@@ -126,7 +126,7 @@ sdp_remove_codecs_by_name("PCMU,PCMA,GSM");
 	</section>
 	</section>
 	<section id="sdpops.f.remove_line_by_prefix">
 	<section id="sdpops.f.remove_line_by_prefix">
 	<title>
 	<title>
-		<function moreinfo="none">sdp_remove_line_by_prefix(string)</function>
+		<function moreinfo="none">sdp_remove_line_by_prefix(string [, mtype])</function>
 	</title>
 	</title>
 	<para>
 	<para>
 			Remove all SDP attribute lines beginning with 'string'
 			Remove all SDP attribute lines beginning with 'string'

+ 111 - 35
modules/sdpops/sdpops_mod.c

@@ -42,7 +42,7 @@
 
 
 MODULE_VERSION
 MODULE_VERSION
 
 
-static int w_sdp_remove_line_by_prefix(sip_msg_t* msg, char* prefix, char* bar);
+static int w_sdp_remove_line_by_prefix(sip_msg_t* msg, char* prefix, char* media);
 static int w_sdp_remove_codecs_by_id(sip_msg_t* msg, char* codecs, char *media);
 static int w_sdp_remove_codecs_by_id(sip_msg_t* msg, char* codecs, char *media);
 static int w_sdp_remove_codecs_by_name(sip_msg_t* msg, char* codecs, char *media);
 static int w_sdp_remove_codecs_by_name(sip_msg_t* msg, char* codecs, char *media);
 static int w_sdp_keep_codecs_by_id(sip_msg_t* msg, char* codecs, char *media);
 static int w_sdp_keep_codecs_by_id(sip_msg_t* msg, char* codecs, char *media);
@@ -73,6 +73,8 @@ static int mod_init(void);
 static cmd_export_t cmds[] = {
 static cmd_export_t cmds[] = {
 	{"sdp_remove_line_by_prefix",  (cmd_function)w_sdp_remove_line_by_prefix,
 	{"sdp_remove_line_by_prefix",  (cmd_function)w_sdp_remove_line_by_prefix,
 		1, fixup_spve_null,  0, ANY_ROUTE},
 		1, fixup_spve_null,  0, ANY_ROUTE},
+	{"sdp_remove_line_by_prefix",  (cmd_function)w_sdp_remove_line_by_prefix,
+		2, fixup_spve_spve,  0, ANY_ROUTE},
 	{"sdp_remove_codecs_by_id",    (cmd_function)w_sdp_remove_codecs_by_id,
 	{"sdp_remove_codecs_by_id",    (cmd_function)w_sdp_remove_codecs_by_id,
 		1, fixup_spve_null,  0, ANY_ROUTE},
 		1, fixup_spve_null,  0, ANY_ROUTE},
 	{"sdp_remove_codecs_by_id",    (cmd_function)w_sdp_remove_codecs_by_id,
 	{"sdp_remove_codecs_by_id",    (cmd_function)w_sdp_remove_codecs_by_id,
@@ -390,31 +392,7 @@ int sdp_remove_codecs_by_id(sip_msg_t* msg, str* codecs, str* media)
 	return 0;
 	return 0;
 }
 }
 
 
-/**
- * @brief remove all SDP lines that begin with prefix
- * @return -1 - error; 0 - no lines found ; 1..N - N lines deleted
- */
-int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix)
-{
-	str body = {NULL, 0};
-
-	if(parse_sdp(msg) != 0) {
-		LM_ERR("Unable to parse SDP\n");
-		return -1;
-	}
-
-	body.s = ((sdp_info_t*)msg->body)->raw_sdp.s;
-	body.len = ((sdp_info_t*)msg->body)->raw_sdp.len;
-
-	if (body.s==NULL) {
-		LM_ERR("failed to get the message body\n");
-		return -1;
-	}
-
-	if (body.len==0) {
-		LM_DBG("message body has zero length\n");
-		return -1;
-	}
+int sdp_remove_line_lump_by_prefix(sip_msg_t* msg, str* body, str* prefix) {
 
 
 	char *ptr = NULL;
 	char *ptr = NULL;
 	str line = {NULL, 0};
 	str line = {NULL, 0};
@@ -422,7 +400,7 @@ int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix)
 	int found = 0;
 	int found = 0;
 	struct lump *anchor = NULL;
 	struct lump *anchor = NULL;
 
 
-	ptr = find_sdp_line(body.s, body.s + body.len, prefix->s[0]);
+	ptr = find_sdp_line(body->s, body->s + body->len, prefix->s[0]);
 	while (ptr)
 	while (ptr)
 	{
 	{
 		if (sdp_locate_line(msg, ptr, &line) != 0)
 		if (sdp_locate_line(msg, ptr, &line) != 0)
@@ -431,9 +409,9 @@ int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix)
 			return -1;
 			return -1;
 		}
 		}
 
 
-		if (body.s + body.len < line.s + prefix->len) // check if strncmp would run too far
+		if (body->s + body->len < line.s + prefix->len) // check if strncmp would run too far
 		{
 		{
-			//LM_DBG("done searching, prefix string >%.*s< (%d) does not fit into remaining buffer space (%ld) \n", prefix->len, prefix->s, prefix->len, body.s + body.len - line.s);
+			//LM_DBG("done searching, prefix string >%.*s< (%d) does not fit into remaining buffer space (%ld) \n", prefix->len, prefix->s, prefix->len, body->s + body->len - line.s);
 			break;
 			break;
 		}
 		}
 
 
@@ -465,7 +443,7 @@ int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix)
 			//LM_DBG("updated remove >%.*s< (%d)\n", remove.len, remove.s, remove.len);
 			//LM_DBG("updated remove >%.*s< (%d)\n", remove.len, remove.s, remove.len);
 
 
 		}
 		}
-		ptr = find_next_sdp_line(ptr, body.s + body.len, prefix->s[0], NULL);
+		ptr = find_next_sdp_line(ptr, body->s + body->len, prefix->s[0], NULL);
 	}
 	}
 
 
 	if (found) {
 	if (found) {
@@ -483,13 +461,102 @@ int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix)
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ * @brief remove all SDP lines that begin with prefix
+ * @return -1 - error; 0 - no lines found ; 1..N - N lines deleted
+ */
+int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix, str* media)
+{
+	str body = {NULL, 0};
+	int sdp_session_num = 0;
+	int sdp_stream_num = 0;
+	int found = 0;
+
+	if(parse_sdp(msg) != 0) {
+		LM_ERR("Unable to parse SDP\n");
+		return -1;
+	}
+
+	body.s = ((sdp_info_t*)msg->body)->raw_sdp.s;
+	body.len = ((sdp_info_t*)msg->body)->raw_sdp.len;
+
+	if (body.s==NULL) {
+		LM_ERR("failed to get the message body\n");
+		return -1;
+	}
+
+	if (body.len==0) {
+		LM_DBG("message body has zero length\n");
+		return -1;
+	}
+
+	if (media->s==NULL || media->len==0 ) {
+		LM_DBG("media type filter not set\n");
+		found = sdp_remove_line_lump_by_prefix(msg, &body, prefix);
+	} else {
+		LM_DBG("using media type filter: %.*s\n",media->len, media->s);
+
+		sdp_session_cell_t* sdp_session;
+		sdp_stream_cell_t* sdp_stream;
+
+		sdp_session_num = 0;
+		for (;;) {
+			sdp_session = get_sdp_session(msg, sdp_session_num);
+			if(!sdp_session) break;
+			sdp_stream_num = 0;
+			for (;;) {
+				sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
+				if(!sdp_stream) break;
+				if( sdp_stream->media.len == media->len &&
+					strncasecmp(sdp_stream->media.s, media->s, media->len) == 0) {
+
+					LM_DBG("range for media type %.*s: %ld - %ld\n",
+							sdp_stream->media.len, sdp_stream->media.s,
+							sdp_stream->raw_stream.s - body.s,
+							sdp_stream->raw_stream.s + sdp_stream->raw_stream.len - body.s
+					);
+
+					found += sdp_remove_line_lump_by_prefix(msg,&(sdp_stream->raw_stream),prefix);
+
+				}
+				sdp_stream_num++;
+			}
+			sdp_session_num++;
+		}
+	}
+	return found;
+}
+
+
+/*
+
+int sdp_remove_str_codec_id_attrs(sip_msg_t* msg, sdp_stream_cell_t* sdp_stream, str *rm_codec)
+
+	str aline = {0, 0};
+	sdp_payload_attr_t *payload;
+	struct lump *anchor;
+
+	payload = sdp_stream->payload_attr;
+	while (payload) {
+		LM_DBG("a= ... for codec %.*s/%.*s\n",
+				payload->rtp_payload.len, payload->rtp_payload.s,
+				payload->rtp_enc.len, payload->rtp_enc.s);
+		if(rm_codec->len==payload->rtp_payload.len
+				&& strncmp(payload->rtp_payload.s, rm_codec->s,
+					rm_codec->len)==0) {
+			if(payload->rtp_enc.s!=NULL) {
+				if(sdp_locate_line(msg, payload->rtp_enc.s, &aline)==0)
+*/
+
+
 /**
 /**
  * removes all SDP lines that begin with script provided prefix
  * removes all SDP lines that begin with script provided prefix
  * @return -1 - error; 1 - found
  * @return -1 - error; 1 - found
  */
  */
-static int w_sdp_remove_line_by_prefix(sip_msg_t* msg, char* prefix, char* bar)
+static int w_sdp_remove_line_by_prefix(sip_msg_t* msg, char* prefix, char* media)
 {
 {
-	str prfx = {NULL, 0};
+	str lprefix = {NULL, 0};
+	str lmedia = {NULL, 0};
 
 
 	if(prefix==0)
 	if(prefix==0)
 	{
 	{
@@ -497,14 +564,23 @@ static int w_sdp_remove_line_by_prefix(sip_msg_t* msg, char* prefix, char* bar)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if (get_str_fparam(&prfx, msg, (fparam_t*)prefix))
+	if (get_str_fparam(&lprefix, msg, (fparam_t*)prefix))
 	{
 	{
 		LM_ERR("unable to determine prefix\n");
 		LM_ERR("unable to determine prefix\n");
 		return -1;
 		return -1;
 	}
 	}
-	LM_DBG("Removing SDP lines with prefix: %.*s\n", prfx.len, prfx.s);
 
 
-	if ( sdp_remove_line_by_prefix(msg, &prfx) < 0)
+	if (media != NULL) {
+		if (get_str_fparam(&lmedia, msg, (fparam_t*)media))
+		{
+			LM_ERR("unable to get the media type\n");
+			return -1;
+		}
+	}
+
+	LM_DBG("Removing SDP lines with prefix: %.*s\n", lprefix.len, lprefix.s);
+
+	if ( sdp_remove_line_by_prefix(msg, &lprefix, &lmedia) < 0)
 		return -1;
 		return -1;
 	return 1;
 	return 1;
 }
 }

+ 31 - 0
test/unit/60-message-sdp9.sip

@@ -0,0 +1,31 @@
+MESSAGE sip:[email protected] SIP/2.0
+From: sip:[email protected];tag=45dfdf49
+To: sip:[email protected]
+Call-ID: 1172299593a
+CSeq: 1 MESSAGE
+Content-Type: application/sdp
+Max-Forwards: 2
+X-Case: 60-test9
+X-Info: sdpops remove_line_by_prefix test9 - filter video attribute
+
+v=0
+o=FreeSWITCH 1447318678 1447318679 IN IP4 10.0.0.145
+s=FreeSWITCH
+c=IN IP4 10.0.0.145
+t=0 0
+m=audio 28504 RTP/AVP 96 101
+a=rtpmap:96 opus/48000/2
+a=fmtp:96 useinbandfec=1; maxaveragebitrate=14400; maxplaybackrate=8000
+a=rtpmap:101 telephone-event/48000
+a=fmtp:101 0-16
+a=ptime:20
+a=sendrecv
+a=rtcp:28505 IN IP4 10.0.0.145
+a=rtcp-fb:101 nack
+m=video 21992 RTP/SAVPF 100
+a=rtpmap:100 VP8/90000
+a=rtcp:21992 IN IP4 10.0.0.150
+a=rtcp-fb:100 ccm fir
+a=rtcp-fb:100 nack
+a=rtcp-fb:100 nack pli
+

+ 7 - 0
test/unit/60.cfg

@@ -26,6 +26,13 @@ route {
 			sl_send_reply(200,"OK");
 			sl_send_reply(200,"OK");
 			exit;
 			exit;
 		}
 		}
+		if ($hdr(X-Case) == '60-test9') {
+			sdp_remove_line_by_prefix("a=rtcp","video");
+			msg_apply_changes();
+			set_reply_body($rb,"application/sdp");
+			sl_send_reply(200,"OK");
+			exit;
+		}
 		sl_send_reply(500,"Unknown test case");
 		sl_send_reply(500,"Unknown test case");
 		exit;
 		exit;
 
 

+ 29 - 7
test/unit/60.sh

@@ -20,26 +20,27 @@
 . include/common
 . include/common
 . include/require.sh
 . include/require.sh
 
 
-CFG=60.cfg
+CFGFILE=60.cfg
 TMPFILE=$(mktemp -t kamailio-test.XXXXXXXXXX)
 TMPFILE=$(mktemp -t kamailio-test.XXXXXXXXXX)
+SIPSAKOPTS="-H localhost -s sip:127.0.0.1 -v"
 
 
 if ! (check_sipsak && check_kamailio && check_module "sdpops"); then
 if ! (check_sipsak && check_kamailio && check_module "sdpops"); then
 	exit 0
 	exit 0
 fi
 fi
 
 
-${BIN} -w . -f ${CFG} > /dev/null
+${BIN} -w ${RUN_DIR} -Y ${RUN_DIR} -P ${PIDFILE} -f ${CFGFILE} > /dev/null
 ret=$?
 ret=$?
 
 
 sleep 1
 sleep 1
 if [ "${ret}" -ne 0 ] ; then
 if [ "${ret}" -ne 0 ] ; then
 	echo "start fail"
 	echo "start fail"
-	${KILL}
+	kill_kamailio
 	exit ${ret}
 	exit ${ret}
 fi
 fi
 
 
 # Borken SDP should give 500 response
 # Borken SDP should give 500 response
 FILE="60-message-sdp0.sip"
 FILE="60-message-sdp0.sip"
-sipsak -f ${FILE} -L -s sip:127.0.0.1 -v > ${TMPFILE}
+sipsak ${SIPSAKOPTS} -f ${FILE} > ${TMPFILE}
 ret=$?
 ret=$?
 if [ "${ret}" -eq 1 ] ; then
 if [ "${ret}" -eq 1 ] ; then
 	ret=0
 	ret=0
@@ -55,7 +56,7 @@ for i in 1 2 3 4 5 6 7; do
 	TOTALBEFORE=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=X-cap/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${FILE})
 	TOTALBEFORE=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=X-cap/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${FILE})
 	OTHERBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f1)
 	OTHERBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f1)
 
 
-	sipsak -f ${FILE} -L -s sip:127.0.0.1 -v > ${TMPFILE}
+	sipsak ${SIPSAKOPTS} -f ${FILE} > ${TMPFILE}
 	ret=$?
 	ret=$?
 	if [ "${ret}" -eq 0 ] ; then
 	if [ "${ret}" -eq 0 ] ; then
 		TOTALAFTER=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=X-cap/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${TMPFILE})
 		TOTALAFTER=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=X-cap/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${TMPFILE})
@@ -74,7 +75,7 @@ done
 
 
 # Empty body should get 500 response
 # Empty body should get 500 response
 FILE="60-message-sdp8.sip"
 FILE="60-message-sdp8.sip"
-sipsak -f ${FILE} -L -s sip:127.0.0.1 -v > ${TMPFILE}
+sipsak ${SIPSAKOPTS} -f ${FILE} > ${TMPFILE}
 ret=$?
 ret=$?
 if [ "${ret}" -eq 1 ] ; then
 if [ "${ret}" -eq 1 ] ; then
 	ret=0
 	ret=0
@@ -84,7 +85,28 @@ else
 	exit ${ret}
 	exit ${ret}
 fi
 fi
 
 
-${KILL}
+# Filter only video stream attributes
+FILE="60-message-sdp9.sip"
+TOTALBEFORE=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=rtcp/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${FILE})
+OTHERBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f1)
+PREFIXBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f2)
+sipsak ${SIPSAKOPTS} -f ${FILE} > ${TMPFILE}
+ret=$?
+if [ "${ret}" -eq 0 ] ; then
+	TOTALAFTER=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=rtcp:/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${TMPFILE})
+	OTHERAFTER=$(echo ${TOTALBEFORE}|cut -d+ -f1)
+	PREFIXAFTER=$(echo ${TOTALAFTER}|cut -d+ -f2)
+	if [ ${PREFIXAFTER} -eq 1 ] && [ ${OTHERBEFORE} -eq ${OTHERAFTER} ]; then
+		ret=0
+	else
+		ret=1
+		echo "found ${PREFIXAFTER} lines with prefix \"a=rtcp\", was expecting 1 (in m=audio)(${FILE})"
+	fi
+	else
+		echo "invalid sipsak return: ${ret}"
+fi
 
 
+kill_kamailio
+rm ${TMPFILE}
 exit ${ret}
 exit ${ret}
 
 

+ 29 - 0
test/unit/61-message-sdp.sip

@@ -0,0 +1,29 @@
+MESSAGE sip:[email protected] SIP/2.0
+From: sip:[email protected];tag=45dfdf49
+To: sip:[email protected]
+Call-ID: 1172299593a
+CSeq: 1 MESSAGE
+Content-Type: application/sdp
+Max-Forwards: 2
+X-Info: test lua sr.sdpops.sdp_remove_line_by_prefix
+
+v=0
+o=FreeSWITCH 1447318678 1447318679 IN IP4 10.0.0.145
+s=FreeSWITCH
+c=IN IP4 10.0.0.145
+t=0 0
+m=audio 28504 RTP/AVP 96 101
+a=rtpmap:96 opus/48000/2
+a=fmtp:96 useinbandfec=1; maxaveragebitrate=14400; maxplaybackrate=8000
+a=rtpmap:101 telephone-event/48000
+a=fmtp:101 0-16
+a=ptime:20
+a=sendrecv
+a=rtcp:28505 IN IP4 10.0.0.145
+a=rtcp-fb:101 nack
+m=video 21992 RTP/SAVPF 100
+a=rtpmap:100 VP8/90000
+a=rtcp:21992 IN IP4 10.0.0.150
+a=rtcp-fb:100 ccm fir
+a=rtcp-fb:100 nack
+a=rtcp-fb:100 nack pli

+ 52 - 0
test/unit/61.cfg

@@ -0,0 +1,52 @@
+# ----------- global configuration parameters ------------------------
+debug=2
+fork=yes
+log_stderror=no
+children=1
+disable_tcp=yes
+listen=udp:127.0.0.1:5060
+auto_aliases=no
+alias=example.invalid
+# ------------------ module loading ----------------------------------
+loadpath "../../modules/"
+
+loadmodule "sl.so"
+loadmodule "pv.so"
+loadmodule "textops.so"
+loadmodule "textopsx.so"
+loadmodule "sdpops.so"
+loadmodule "app_lua.so"
+modparam("sl", "bind_tm", 0)
+modparam("app_lua", "register", "sdpops")
+
+request_route {
+	if ( is_present_hf("X-Case") ) {
+		if ( $hdr(X-Case) == '61-test0') {
+			if( !lua_dostring("sr.sdpops.sdp_remove_line_by_prefix([[a=rtcp]])") ) {
+				sl_send_reply(500,"Lua call failed retcode=$retcode ($hdr(X-Case))");
+				exit;
+			}
+		} else if ( $hdr(X-Case) == '61-test1') {
+			if( !lua_dostring("sr.sdpops.sdp_remove_line_by_prefix([[a=rtcp]], [[audio]])") ) {
+				sl_send_reply(500,"Lua call failed retcode=$retcode ($hdr(X-Case))");
+				exit;
+			}
+		} else if ( $hdr(X-Case) == '61-test2') {
+			if( !lua_dostring("sr.sdpops.sdp_remove_line_by_prefix([[a=rtcp]], [[video]])") ) {
+				sl_send_reply(500,"Lua call failed retcode=$retcode ($hdr(X-Case))");
+				exit;
+			}
+		} else {
+			sl_send_reply(500,"Unknown test case");
+			exit;
+		}
+
+ 		msg_apply_changes();
+		set_reply_body($rb,"application/sdp");
+		sl_send_reply(200,"OK");
+		exit;
+	}
+	sl_send_reply(500,"X-Case missing");
+	exit;
+}
+

+ 124 - 0
test/unit/61.sh

@@ -0,0 +1,124 @@
+#!/bin/sh
+# checks sdpops module function sdp_remove_line_by_prefix() via Lua
+#
+# Copyright (C) 2016 [email protected]
+#
+# This file is part of Kamailio, a free SIP server.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+. include/common
+. include/require.sh
+
+CFGFILE=61.cfg
+TMPFILE=$(mktemp -t kamailio-test.XXXXXXXXXX)
+SIPSAKOPTS="-H localhost -s sip:127.0.0.1:5060 -v"
+
+end_test() {
+	kill_kamailio
+	rm ${TMPFILE}
+	exit ${ret}
+}
+
+if ! (check_sipsak && check_kamailio && check_module "sdpops" && check_module "app_lua"); then
+	exit 0
+fi
+
+${BIN} -w ${RUN_DIR} -Y ${RUN_DIR} -P ${PIDFILE} -f ${CFGFILE} > /dev/null
+ret=$?
+
+sleep 1
+if [ "${ret}" -ne 0 ] ; then
+	end_test
+fi
+
+# manipulate whole SDP
+FILE="61-message-sdp.sip"
+TESTCASE="61-test0"
+TOTALBEFORE=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=rtcp/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${FILE})
+OTHERBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f1)
+PREFIXBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f2)
+sipsak ${SIPSAKOPTS} -f ${FILE} --headers "X-Case: ${TESTCASE}\n" > ${TMPFILE}
+ret=$?
+if [ "${ret}" -ne 0 ] ; then
+	echo "sipsak returned ${ret}, aborting"
+	cat ${TMPFILE}
+else
+	TOTALAFTER=$(awk '/^v=0/,/^$/ {total++; if ($0 ~ /^a=rtcp:/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${TMPFILE})
+	OTHERAFTER=$(echo ${TOTALAFTER}|cut -d+ -f1)
+	PREFIXAFTER=$(echo ${TOTALAFTER}|cut -d+ -f2)
+	if [ ${PREFIXAFTER} -eq 0 ]; then
+		ret=0
+	else
+		ret=1
+		echo "test ${TESTCASE} failed"
+		echo "found ${PREFIXAFTER} lines with prefix \"a=rtcp\", was expecting 0"
+		echo "found ${OTHERAFTER} other lines (was ${OTHERBEFORE} before)"
+		end_test
+	fi
+fi
+
+# manipulate m=audio only
+FILE="61-message-sdp.sip"
+TESTCASE="61-test1"
+TOTALBEFORE=$(awk '/^m=audio/,/^m=video/ {total++; if ($0 ~ /^a=rtcp/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${FILE})
+OTHERBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f1)
+PREFIXBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f2)
+sipsak ${SIPSAKOPTS} -f ${FILE} --headers "X-Case: ${TESTCASE}\n" > ${TMPFILE}
+ret=$?
+if [ "${ret}" -ne 0 ] ; then
+	echo "sipsak returned ${ret}, aborting"
+	cat ${TMPFILE}
+else
+	TOTALAFTER=$(awk '/^m=audio/,/^m=video/ {total++; if ($0 ~ /^a=rtcp:/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${TMPFILE})
+	OTHERAFTER=$(echo ${TOTALAFTER}|cut -d+ -f1)
+	PREFIXAFTER=$(echo ${TOTALAFTER}|cut -d+ -f2)
+	if [ ${PREFIXAFTER} -eq 0 ]; then
+		ret=0
+	else
+		ret=1
+		echo "test ${TESTCASE} failed"
+		echo "found ${PREFIXAFTER} lines with prefix \"a=rtcp\", was expecting 0"
+		echo "found ${OTHERAFTER} other lines (was ${OTHERBEFORE} before)"
+		end_test
+	fi
+fi
+
+# manipulate m=video only
+FILE="61-message-sdp.sip"
+TESTCASE="61-test2"
+TOTALBEFORE=$(awk '/^m=video/,/^$/ {total++; if ($0 ~ /^a=rtcp/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${FILE})
+OTHERBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f1)
+PREFIXBEFORE=$(echo ${TOTALBEFORE}|cut -d+ -f2)
+sipsak ${SIPSAKOPTS} -f ${FILE} --headers "X-Case: ${TESTCASE}\n" > ${TMPFILE}
+ret=$?
+if [ "${ret}" -ne 0 ] ; then
+	echo "sipsak returned ${ret}, aborting"
+	cat ${TMPFILE}
+else
+	TOTALAFTER=$(awk '/^m=video/,/^$/ {total++; if ($0 ~ /^a=rtcp:/ ) { prefix++;} else { other++} } END {if (prefix) {print other " + " prefix} else { print other " + 0"} }' ${TMPFILE})
+	OTHERAFTER=$(echo ${TOTALAFTER}|cut -d+ -f1)
+	PREFIXAFTER=$(echo ${TOTALAFTER}|cut -d+ -f2)
+	if [ ${PREFIXAFTER} -eq 0 ]; then
+		ret=0
+	else
+		ret=1
+		echo "test ${TESTCASE} failed"
+		echo "found ${PREFIXAFTER} lines with prefix \"a=rtcp\", was expecting 0"
+		echo "found ${OTHERAFTER} other lines (was ${OTHERBEFORE} before)"
+		end_test
+	fi
+fi
+
+end_test
+

+ 2 - 0
test/unit/include/common

@@ -1,6 +1,7 @@
 # all database modules
 # all database modules
 DB_ALL_MOD="acc|alias_db|auth_db|avpops|dialog|dialplan|dispatcher|domain|domainpolicy|group|imc|lcr|msilo|siptrace|speeddial|uri_db|usrloc|permissions|pdt|userblacklist"
 DB_ALL_MOD="acc|alias_db|auth_db|avpops|dialog|dialplan|dispatcher|domain|domainpolicy|group|imc|lcr|msilo|siptrace|speeddial|uri_db|usrloc|permissions|pdt|userblacklist"
 # root directory relative to tests
 # root directory relative to tests
+RUN_DIR="."
 SRC_DIR="../.."
 SRC_DIR="../.."
 CTL_DIR="$SRC_DIR/utils/kamctl"
 CTL_DIR="$SRC_DIR/utils/kamctl"
 CTLRC="$CTL_DIR/kamctlrc"
 CTLRC="$CTL_DIR/kamctlrc"
@@ -19,5 +20,6 @@ else
     fi
     fi
 fi
 fi
 KILL="killall -15 $BNAME"
 KILL="killall -15 $BNAME"
+PIDFILE="${RUN_DIR}/kamailio.pid"
 # test directory relative to root
 # test directory relative to root
 TEST_DIR="test/unit"
 TEST_DIR="test/unit"

+ 4 - 0
test/unit/include/require.sh

@@ -63,3 +63,7 @@ check_sipsak() {
 	fi;
 	fi;
 	return 0
 	return 0
 }
 }
+
+kill_kamailio() {
+	kill $(cat ${PIDFILE})
+}