Table Of Contents
SDP APIs
Line Level APIs
Cisco API's
getLine
modifyLine
addline
insertLineAfter
insertLineBefore
removeLine
Media Description Level APIs
getMediaDescription(media-level)
getMediaDescription(media-contains)
modifyMediaDescription(media-level, media-description)
modifyMediaDescription(media-contains, media-description)
addMediaDescription(media-description)
insertMediaDescription(media-level, media-description)
removeMediaDescription(media-level)
removeMediaDescription(media-contains)
SDP APIs
This section covers the APIs associated with Session Description Protocol (SDP) content bodies. Unlike the SIP Message object, the SDP is treated as a basic string. This allows the script writer to leverage the power of the Lua string library. In addition to the Lua string library functions, Cisco also provides some APIs to facilitate SDP manipulation. The Cisco APIs are added directly to the string library.
However, before the script can manipulate the SDP, it must obtain the SDP content body from the Lua SIP Message object using the getSdp() API provided by the SIP Message object. The script can then use the string library including Cisco's APIs to manipulate the SDP. On modiifcation, the SDP is written back to the SIP Message object using the setSdp(sdp) API provided by the SIP Message object. Refer to the following SIP Messages APIs for further information of these APIs.
-- Get the SDP content body from the SIP message
-- modification of the SDP happens at this point
-- Update the SDP associated with the SIP message
For the purposes of manipulating the SDP, Cisco provides APIs for getting, modifying, adding, inserting, and removing individual lines as well as entire media descriptions. The remainder of this section will discuss the Cisco APIs.
In order to get and manipulate any line in the SDP, we need a way to identify them. The script writer must be capable of affecting invalid SDPs. Hence, knowledge of the structure of SDP for the purposes of normalization must be minimized. It is difficult, if not impossible, to affect invalid SDP. It is also possible to manipulate valid SDP. With these goals in mind, a string based approach is warranted.
The Lua APIs for manipulating SDP can be classified under two broad classes.
•
Line Level APIs—This set of APIs is directed towards being able to get and manipulate lines within the SDP while
•
Media Description Level APIs—This set of APIs is geared towards manipulating particular media descriptions.
Manipulating session level lines would leverage the Line Level set of APIs while manipulating the media descriptions would leverage the Media Description Level set of APIs.
Note
The set of APIs designed for manipulating lines is not limited to session level lines only.
Line Level APIs
Cisco API's
The following Cisco line level APIs are availabe:
•
getLine( start-of-line , line-contains)
•
modifyLine(start-of-line, line-contains ,new- line )
•
addline(new-line)
•
insertLineAfter( start-of-line, line-contains, new-line)
•
insertLineBefore( start-of-line, line-contains, new-line)
•
removeLine(start-of-line, line-contains)
Parameter Description
Parameter
|
Description
|
sdp
|
The sdp parameter is a string that contains the SDP, including all control characters (i.e. '\r' and '\n'). The APIs do not enforce any SDP structure on the sdp parameter, It treats it like a string. The script writer can use the APIs to operate on parts of SDP ( for example a audio media description).
|
start-of-line
|
The start-of-line parameter is a string used to match the start of a line in sdp. In typical scripts, for example, "o=" "a=rtpmap:9" can be used to get/modify/insert/remove the first line in sdp which starts with this string. If there are multiple lines that start with this string , only the first line is considered.
This parameter MUST be of the form <char>=<string> . i.e. the second character must be the equal sign. If the parameter does not have this format , a 'nil' is returned .
|
line-contains
|
The line-contains is a string used as an additional match criterion to search within the line starting with 'start-of-line' parameter. If nil is specified, line-contains is not used as a match criterion. In that case, only the start-of-line parameter will be used for matching.
When line-contains is not nil, both the start-of-line and line-contains will be used for matching. If there are multiple lines in SDP that match (both) the search criteria, only the first match will be returned.
If this additional matching, using this parameter is not desired , a value of 'nil' without the quotes needs to be passed in.
|
new-line
|
The new-line is the string that will be added/inserted in the final sdp (returned sdp)
|
The APIs above treat the parameters as strings. Therefore , they can operate on both session level and media level lines. There is no difference in behavior based on whether a line is at session level or media level. It is assumed that lines are terminated with \n( or \r\n) when trying to find the matching line .
No characters in the parameters are considered Lua 'Magic characters'. All characters are considered plain and do not have any special meaning.
getLine
sdp:getLine(start-of-line, line-contains) returns string
This method returns the first line in sdp that starts with start-of-line and also has the string line-contains.
Example: Set a local variable to the value of the c-line from the SDP.
Script
function M.outbound_INVITE(msg)
local ipv4_c_line = sdp:getLine("c=", "IP4")
Message
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.88
m=audio 24580 RTP/AVP 0 101
a=rtpmap:101 telephone-event/8000
Output/Result
Local variable ipv4_c_line is set to "c=IN IP4 172.18.197.88\r\n"
modifyLine
sdp:modifyLine(start-of-line, line-contains, new-line)
This method finds the first line in 'sdp' that starts with start-of-line . If line-contains parameter is non-nil, it must be present within that line. The matching line (including the line termination characters) is replaced with new-line parameter. The resulting sdp is returned.
If no matching line is found, the original sdp is returned unchanged.
Note
It is recommended that the caller terminate the new-line with \r\n ( or \n) to comply with SDP rules . No enforcement of line termination characters is done by the utility.
Example: The following code will change a= line for G.722 codec to be G722 without the dot.
Script
function M.inbound_INVITE(msg)
local g722_line = sdp:getLine("a=","G.722")
--Replace G.722 with G722. The dot is special and must be
--escaped using % when using gsub.
g722_line = g722_line:gsub("G%.722", "G722")
sdp = sdp:modifyLine("a=", "G.722", g722_line)
Message
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 23588 RTP/AVP 9 0 8 18 101
a=rtpmap:101 telephone-event/8000
Output/Result
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 23588 RTP/AVP 9 0 8 18 101
a=rtpmap:101 telephone-event/8000
addline
This method adds new-line at the end of SDP. It is recommended that the caller terminate the new-line with \r\n ( or \n) to comply with SDP rules . No enforcement of line termination characters is done by this API.
Example: Append an attribute line to the end of the SDP.
Script
function M.outbound_INVITE(msg)
sdp = sdp:addLine("a=some-attribute\r\n")
Message
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.88
m=audio 24690 RTP/AVP 0 101
a=rtpmap:101 telephone-event/8000
Output/Result
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.88
m=audio 24690 RTP/AVP 0 101
a=rtpmap:101 telephone-event/8000
insertLineAfter
sdp:insertLineAfter(start-of-line, line-contains, new-line)
This method finds the first line in sdp that starts with start-of-line and also has line-contains in that line, if line-contains parameter is specified . It will insert new-line after the found line.
Example: Insert a line into the SDP after the line with "a=" and "G729".
Script
function M.outbound_INVITE(msg)
sdp = sdp:insertLineAfter("a=", "G729", "a=ptime:30\r\n")
Message
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 21702 RTP/AVP 18 101
a=rtpmap:101 telephone-event/8000
Output/Result
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 21702 RTP/AVP 18 101
a=rtpmap:101 telephone-event/8000
insertLineBefore
sdp:insertLineBefore(start-of-line, line-contains, new-line)
This method finds the first line in sdp that starts with start-of-line and also has line-contains in that line, if line-contains parameter is specified . It will insert new-line before the found line.
Example: Insert a line into the SDP prior to the "s=" line.
Script
function M.inbound_ANY_INVITE(msg)
sdp= sdp:insertLineBefore("s=", nil, "e=nobody@cisco.com\r\n")
Message
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 17774 RTP/AVP 9 101
a=rtpmap:101 telephone-event/8000
Output/Result
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 17774 RTP/AVP 9 101
a=rtpmap:101 telephone-event/8000
removeLine
sdp:removeLine(start-of-line, line-contains)
This method finds the first line in 'sdp' that starts with 'start-of-line' AND also has 'line-contains' in that line if 'line-contains' parameter is specified. The matching line is removed from the sdp.
Example: Remove the line containing both "a=rtpmap" and "G729" from the SDP.
Script
function M.inbound_INVITE(msg)
sdp = sdp:removeLine("a=rtpmap:", "G729")
Message
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 25328 RTP/AVP 9 0 8 18 101
a=rtpmap:101 telephone-event/8000
Output/Result
INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
Content-Type: application/sdp
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
m=audio 25328 RTP/AVP 9 0 8 18 101
a=rtpmap:101 telephone-event/8000
Media Description Level APIs
The following APIs are used to get and manipulate SDP media levels:
SDP Example
In the following SDP example, the session level lined are shown in green while blue denotes media-level lines.
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
In the SDP example provided above, the media-level indices are in blue color. Media level [1] is an audio media description. Media level [2] is a video media description (not shown in its entirety).
All indices are 1 based. Hence, the first media description is at index 1. The second is at index 2 and so on.
The following Medi Description level APIs are availabe:
•
getMediaDescription(media-level)
•
getMediaDescription(media-contains)
•
modifyMediaDescription(media-level, media-description)
•
modifyMediaDescription(media-contains, media-description)
•
addMediaDescription(media-description)
•
insertMediaDescription(media-level, media-description)
•
removeMediaDescription(media-level)
•
removeMediaDescription(media-contains)
Parameter Description
Parameter
|
Description
|
sdp
|
The sdp object is a string containing the SDP including all control characters (i.e. '\r' and '\n').
|
media-level
|
The media-level parameter is an index used to reference a media description within the SDP. The indices are 1 based. The first media description within the SDP is at media level 1. The second is at media level 2 and so on.
|
media-contains
|
The media-contains parameter is a string used to match something (e.g. the media type) within the m-line.
For example, audio, video, and message can be used to get, modify, or remove the first occurrence of a media description where the m-line contains an exact match of the media-contains value.
|
media-description
|
The media-description parameter is a string contains a complete media description including multiple lines and the necessary embedded control characters: '\r' and '\n'.
It is highly recommended that the last line be terminated with "\r\n". Although these APIs are purely text manipulations and no rules about the format of the text are enforced. In fact, some implementations don't actually include the '\r' at the end of each line. Treating this as pure text provides the necessary flexibility to handle either case and even convert easily between the two styles (e.g. it would be trivial to change "\r\n" to "\n" or vice versa).
The following string is an example of a complete media description:
"m=audio 18884 RTP/AVP 9\r\na=rtpmap:9 G722/8000\r\n"
|
The details of each media related API is described in the section below.
Note
All indices (i.e. the media-level) are 1 based
getMediaDescription(media-level)
getMediaDescription(media-level) returns media-description
This API is used to get a particular media description at the specified media level.
Example: Set a local variable to the value of the first media description.
Script
function M.outbound_INVITE(msg)
local m1 = sdp:getMediaDescription(1)
Message
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
Output/Result
Local variable m1 is set to a string
m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
getMediaDescription(media-contains)
getMediaDescription(media-contains) returns media-description
This API is used to get a particular media description where media-contains is an exact match for some portion of the m-line.
Note
If multiple m-lines match, only the first matching media-description is returned.
Example: Set a local variable to the value of the first media description whose m-line contains the text "audio".
Script
function M.outbound_INVITE(msg)
local audio = sdp:getMediaDescription("audio")
Message
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
Output/Result
Local variable audio is set to a string
m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
modifyMediaDescription(media-level, media-description)
modifyMediaDescription(media-level, media-description)
This API is used to modify a particular media description at the specified media level.
Example: Remove the lines containing "a=ptime:20\r\n" from the audio media description
Script
function M.outbound_INVITE(msg)
local m1 = sdp:getMediaDescription(1)
m1 = m1:gsub("a=ptime:20\r\n", "")
sdp = sdp:modifyMediaDescription(1, m1)
Message Before Normalization
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
Message After Normailzation
After normalization, the SDP would contain:
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
modifyMediaDescription(media-contains, media-description)
modifyMediaDescription(media-contains, media-description)
This API is used to modify a particular media description where media-contains is an exact match for some portion of the m-line. Note that if multiple m-lines match, only the first matching media-description is modified.
Example: Remove the lines containing "a=ptime:20\r\n" from the audio media description
Script
function M.outbound_INVITE(msg)
local audio = sdp:getMediaDescription("audio")
audio = audio:gsub("a=ptime:20\r\n", "")
sdp = sdp:modifyMediaDescription("audio", audio)
Message Before Normalization
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
Message After Normailzation
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
c=IN IP4 172.18.195.126\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
addMediaDescription(media-description)
addMediaDescription(media-description)
This API is used to add a media description as the last media description.
Example:
The script removes and saves the video media description from inbound INVITEs. The script assumes the video media description is the 2nd media description. For the corresponding outbound responses, the script retrieves the stored video media description, sets the port to zero, and adds the media description into the outbound SDP.
Script
function M.inbound_INVITE(msg)
local video = sdp:getMediaDescription(2)
--remove the video media description
sdp = sdp:removeMediaDescription(2)
--store video media description
local context = msg:getContext()
function M.outbound_ANY_INVITE(msg)
--assume other side is expecting video before audio when there is
--a video m-line in the SDP
local context = msg:getContext()
local video = context["video"]
--set port to zero in SDP answer
video = video:gsub("video %d* RTP", "video 0 RTP")
sdp = sdp:addMediaDescription(video)
Message Before Normalization
o=- 2000 3 IN IP4 10.10.10.100\r\n
c=IN IP4 10.10.10.100\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
[2] m=video 32068 RTP/AVP 112 113 114\r\n
a=rtpmap:112 H264/90000\r\n
a=fmtp:112
profile-level-id=4D8028;packetization-mode=1;max-mbps=243000;max-fs=8100\r\n
a=rtpmap:113 H264/90000\r\n
a=fmtp:113 profile-level-id=42400D;packetization-mode=1;max-mbps=11880;max-fs=396\r\n
a=rtpmap:114 H264/90000\r\n
a=fmtp:114 profile-level-id=42400D;packetization-mode=0;max-mbps=11880;max-fs=396\r\n
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
c=IN IP4 10.10.10.200\r\n
[1] m=audio 16007 RTP/AVP 9 18 101\r\n
a=rtpmap:101 telephone-event/8000\r\n
Message After Normalization
o=- 2000 3 IN IP4 10.10.10.100\r\n
c=IN IP4 10.10.10.100\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
c=IN IP4 10.10.10.200\r\n
[1] m=audio 16007 RTP/AVP 9 18 101\r\n
a=rtpmap:101 telephone-event/8000\r\n
[2] m=video 0 RTP/AVP 112 113 114\r\n
a=rtpmap:112 H264/90000\r\n
a=fmtp:112
profile-level-id=4D8028;packetization-mode=1;max-mbps=243000;max-fs=8100\r\n
a=rtpmap:113 H264/90000\r\n
a=fmtp:113 profile-level-id=42400D;packetization-mode=1;max-mbps=11880;max-fs=396\r\n
a=rtpmap:114 H264/90000\r\n
a=fmtp:114 profile-level-id=42400D;packetization-mode=0;max-mbps=11880;max-fs=396\r\n
insertMediaDescription(media-level, media-description)
insertMediaDescription(media-level, media-description)
This API is used to add a media description as the at the specified media level.
Example: Inserting a message media description so that it is the first media description in the SDP
Script
function M.outbound_INVITE(msg)
local message = "m=message 1234 sip:alice@10.10.10.100\r\n"
sdp = sdp:insertMediaDescription(1, message)
Message Before Normalization
o=- 2000 3 IN IP4 10.10.10.100\r\n
c=IN IP4 10.10.10.100\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
Message After Normalization
o=- 2000 3 IN IP4 10.10.10.100\r\n
c=IN IP4 10.10.10.100\r\n
[1] m=message 1234 sip:alice@10.10.10.100\r\n
[2] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
removeMediaDescription(media-level)
removeMediaDescription(media-level)
This API is used to remove the media description at the specified media level.
Example:
Please refer to the example provided by addMediaDescription(media-description). It also uses removeMediaDescription.
removeMediaDescription(media-contains)
removeMediaDescription(media-contains)
This API is used to remove a particular media description where media-contains is an exact match for some portion of the m-line.
Note
If multiple m-lines match, only the first matching media-description is remove.
Example:
The script removes and saves the video media description from inbound INVITEs. For the corresponding outbound responses, the script retrieves the stored video media description, sets the port to zero, and adds the media description into the outbound SDP.
Script
function M.inbound_INVITE(msg)
local video = sdp:getMediaDescription("video")
--remove the video media description
sdp = sdp:removeMediaDescription("video")
--store video media description
local context = msg:getContext()
function M.outbound_ANY_INVITE(msg)
--assume other side is expecting video before audio when there is
--a video m-line in the SDP
local context = msg:getContext()
local video = context["video"]
--set port to zero in SDP answer
video = video:gsub("video %d* RTP", "video 0 RTP")
sdp = sdp:addMediaDescription(video)
Message Before Normalization
o=- 2000 3 IN IP4 10.10.10.100\r\n
c=IN IP4 10.10.10.100\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
[2] m=video 32068 RTP/AVP 112 113 114\r\n
a=rtpmap:112 H264/90000\r\n
a=fmtp:112
profile-level-id=4D8028;packetization-mode=1;max-mbps=243000;max-fs=8100\r\n
a=rtpmap:113 H264/90000\r\n
a=fmtp:113 profile-level-id=42400D;packetization-mode=1;max-mbps=11880;max-fs=396\r\n
a=rtpmap:114 H264/90000\r\n
a=fmtp:114 profile-level-id=42400D;packetization-mode=0;max-mbps=11880;max-fs=396\r\n
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
c=IN IP4 10.10.10.200\r\n
[1] m=audio 16007 RTP/AVP 9 18 101\r\n
a=rtpmap:101 telephone-event/8000\r\n
Message After Normalization
o=- 2000 3 IN IP4 10.10.10.100\r\n
c=IN IP4 10.10.10.100\r\n
[1] m=audio 18884 RTP/AVP 9 18 101\r\n
a=rtpmap:18 G729/8000\r\n
a=rtpmap:101 telephone-event/8000\r\n
o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
c=IN IP4 10.10.10.200\r\n
[1] m=audio 16007 RTP/AVP 9 18 101\r\n
a=rtpmap:101 telephone-event/8000\r\n
[2] m=video 0 RTP/AVP 112 113 114\r\n
a=rtpmap:112 H264/90000\r\n
a=fmtp:112
profile-level-id=4D8028;packetization-mode=1;max-mbps=243000;max-fs=8100\r\n
a=rtpmap:113 H264/90000\r\n
a=fmtp:113 profile-level-id=42400D;packetization-mode=1;max-mbps=11880;max-fs=396\r\n
a=rtpmap:114 H264/90000\r\n
a=fmtp:114 profile-level-id=42400D;packetization-mode=0;max-mbps=11880;max-fs=396\r\n