Developer Guide for SIP Transparency and Normalization
SDP APIs
Downloads: This chapterpdf (PDF - 465.0KB) The complete bookPDF (PDF - 1.92MB) | Feedback

SDP APIs

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
local sdp = msg:getSdp()
-- modification of the SDP happens at this point
-- Update the SDP associated with the SIP message
msg: etSdp(sdp)

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

M = {}
function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local ipv4_c_line = sdp:getLine("c=", "IP4")
    end
end
return M

Message

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.88
s=SIP Call
c=IN IP4 172.18.197.88
t=0 0
m=audio 24580 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

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

M = {}

function M.inbound_INVITE(msg)
    local sdp = msg:getSdp()

    if sdp
    then
        local g722_line = sdp:getLine("a=","G.722")

        if g722_line
        then
            --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)
            msg:setSdp(sdp)
        end
    end
end

return M

Message

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 23588 RTP/AVP 9 0 8 18 101
a=rtpmap:9 G.722/8000
a=ptime:20
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:8 PCMA/8000
a=ptime:20
a=rtpmap:18 G729/8000
a=ptime:20
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

Output/Result

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 23588 RTP/AVP 9 0 8 18 101
a=rtpmap:9 G722/8000
a=ptime:20
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:8 PCMA/8000
a=ptime:20
a=rtpmap:18 G729/8000
a=ptime:20
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

addline

sdp:addLine(new-line)

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

M = {}

function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()

    if sdp
    then
        sdp = sdp:addLine("a=some-attribute\r\n")

        msg:setSdp(sdp)
    end
end

return M

Message

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.88
s=SIP Call
c=IN IP4 172.18.197.88
t=0 0
m=audio 24690 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

Output/Result

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.88
s=SIP Call
c=IN IP4 172.18.197.88
t=0 0
m=audio 24690 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
a=some-attribute

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

M = {}

function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()

    if sdp
    then
        sdp = sdp:insertLineAfter("a=", "G729", "a=ptime:30\r\n")
        msg:setSdp(sdp)
    end
end

return M

Message

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 21702 RTP/AVP 18 101
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

Output/Result

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 21702 RTP/AVP 18 101
a=rtpmap:18 G729/8000^M
a=ptime:30
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

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

M = {}

function M.inbound_ANY_INVITE(msg)    
    local sdp = msg:getSdp()

    if sdp
    then
        sdp= sdp:insertLineBefore("s=", nil, "e=nobody@cisco.com\r\n")
        msg:setSdp(sdp)
    end
end

return M

Message

SIP/2.0 200 OK
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 17774 RTP/AVP 9 101
a=rtpmap:9 G722/8000
a=ptime:20
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

Output/Result

SIP/2.0 200 OK
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
e=nobody@cisco.com
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 17774 RTP/AVP 9 101
a=rtpmap:9 G722/8000
a=ptime:20
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

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

M = {}

function M.inbound_INVITE(msg)
    local sdp = msg:getSdp()

    if sdp
    then
        sdp = sdp:removeLine("a=rtpmap:", "G729")
        msg:setSdp(sdp)
    end
end

return M

Message

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 25328 RTP/AVP 9 0 8 18 101
a=rtpmap:9 G722/8000
a=ptime:20
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:8 PCMA/8000
a=ptime:20
a=rtpmap:18 G729/8000
a=ptime:20
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

Output/Result

INVITE sip:901@rawlings.cisco.com:5080 SIP/2.0
.
Content-Type: application/sdp

v=0
o=CiscoSystemsCCM-SIP 2000 1 IN IP4 172.18.197.22
s=SIP Call
c=IN IP4 172.18.197.29
t=0 0
m=audio 25328 RTP/AVP 9 0 8 18 101
a=rtpmap:9 G722/8000
a=ptime:20
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:8 PCMA/8000
a=ptime:20
a=ptime:20
a=fmtp:18 annexb=no
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

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.

v=0\r\n
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

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

M = {}
function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local m1 = sdp:getMediaDescription(1)
    end
end
return M


Message

v=0\r\n
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

Output/Result

Local variable m1 is set to a string

     m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\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

M = {}
function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local audio = sdp:getMediaDescription("audio")
    end
end
return M

Message

v=0\r\n
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

Output/Result

Local variable audio is set to a string

     m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\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

M = {}
function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local m1 = sdp:getMediaDescription(1)
        if m1
        then
            m1 = m1:gsub("a=ptime:20\r\n", "")
            sdp = sdp:modifyMediaDescription(1, m1)
            msg:setSdp(sdp)
        end
    end
end
return M

Message Before Normalization

v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

Message After Normailzation

After normalization, the SDP would contain:

     v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=rtpmap:18 G729/8000\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

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

M = {}
function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local audio = sdp:getMediaDescription("audio")
        if audio
        then
            audio = audio:gsub("a=ptime:20\r\n", "")
            sdp = sdp:modifyMediaDescription("audio", audio)
            msg:setSdp(sdp)
        end
    end
end
return M

Message Before Normalization

v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

Message After Normailzation

v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 172.18.195.96\r\n
     s=SIP Call\r\n
     c=IN IP4 172.18.195.126\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video...

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

M = {}
function M.inbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local video = sdp:getMediaDescription(2)
        if video
        then
            --remove the video media description
            sdp = sdp:removeMediaDescription(2)
            --store video media description
            local context = msg:getContext()
            context["video"] = video
            msg:setSdp(sdp)
        end
    end
end

function M.outbound_ANY_INVITE(msg)
    local sdp = msg:getSdp()
    --assume other side is expecting video before audio when there is
    --a video m-line in the SDP
    if sdp
    then
        local context = msg:getContext()
        local video = context["video"]
        if video
        then
            --set port to zero in SDP answer
            video = video:gsub("video %d* RTP", "video 0 RTP")
            sdp = sdp:addMediaDescription(video)
            msg:setSdp(sdp)
        end
    end
end
return M

Message Before Normalization

INVITE SDP . . .

     v=0\r\n	
     o=- 2000 3 IN IP4 10.10.10.100\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.100\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video 32068 RTP/AVP 112 113 114\r\n
     b=TIAS:4000000\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
     a=sendrecv\r\n
     \r\n


     200 Ok SDP . . .

     v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.200\r\n
     t=0 0\r\n
[1]  m=audio 16007 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
     \r\n

Message After Normalization

INVITE SDP . . .

     v=0\r\n	
     o=- 2000 3 IN IP4 10.10.10.100\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.100\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
     \r\n

     200 Ok SDP . . .

     v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.200\r\n
     t=0 0\r\n
[1]  m=audio 16007 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video 0 RTP/AVP 112 113 114\r\n
     b=TIAS:4000000\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
     a=sendrecv\r\n
     \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

M = {}
function M.outbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local message = "m=message 1234 sip:alice@10.10.10.100\r\n"
        sdp = sdp:insertMediaDescription(1, message)
        msg:setSdp(sdp)
    end
end
return M

Message Before Normalization

INVITE SDP . . .

     v=0\r\n	
     o=- 2000 3 IN IP4 10.10.10.100\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.100\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n

Message After Normalization

INVITE SDP . . .

     v=0\r\n	
     o=- 2000 3 IN IP4 10.10.10.100\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.100\r\n
     t=0 0\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:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\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

M = {}
function M.inbound_INVITE(msg)
    local sdp = msg:getSdp()
    if sdp
    then
        local video = sdp:getMediaDescription("video")
        if video
        then
            --remove the video media description
            sdp = sdp:removeMediaDescription("video")
            --store video media description
            local context = msg:getContext()
            context["video"] = video
            msg:setSdp(sdp)
        end
    end
end

function M.outbound_ANY_INVITE(msg)
    local sdp = msg:getSdp()
    --assume other side is expecting video before audio when there is
    --a video m-line in the SDP
    if sdp
    then
        local context = msg:getContext()
        local video = context["video"]
        if video
        then
            --set port to zero in SDP answer
            video = video:gsub("video %d* RTP", "video 0 RTP")
            sdp = sdp:addMediaDescription(video)
            msg:setSdp(sdp)
        end
    end
end
return M

Message Before Normalization

INVITE SDP . . .

     v=0\r\n	
     o=- 2000 3 IN IP4 10.10.10.100\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.100\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video 32068 RTP/AVP 112 113 114\r\n
     b=TIAS:4000000\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
     a=sendrecv\r\n
     \r\n

     200 Ok SDP . . .

     v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.200\r\n
     t=0 0\r\n
[1]  m=audio 16007 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
     \r\n

Message After Normalization

INVITE SDP . . .

     v=0\r\n	
     o=- 2000 3 IN IP4 10.10.10.100\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.100\r\n
     t=0 0\r\n
[1]  m=audio 18884 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:18 G729/8000\r\n
     a=ptime:20\r\n
     a=fmtp:18 annexb=no\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
     \r\n 

     200 Ok SDP . . .

     v=0\r\n	
     o=CiscoSystemsCCM-SIP 2000 3 IN IP4 10.10.10.1\r\n
     s=SIP Call\r\n
     c=IN IP4 10.10.10.200\r\n
     t=0 0\r\n
[1]  m=audio 16007 RTP/AVP 9 18 101\r\n
     a=rtpmap:9 G722/8000\r\n
     a=ptime:20\r\n
     a=rtpmap:101 telephone-event/8000\r\n
     a=fmtp:101 0-1\r\n
[2]  m=video 0 RTP/AVP 112 113 114\r\n
     b=TIAS:4000000\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
     a=sendrecv\r\n
     \r\n