SDP API
この章では、Session Description Protocol(SDP; セッション記述プロトコル)のコンテンツ本文に関連した API について説明します。SDP は、SIP Message オブジェクトとは違って、基本文字列として扱われます。このため、スクリプト作成者は、Lua の文字列ライブラリの機能を利用することが可能です。Lua 文字列ライブラリの関数に加えて、シスコからも SDP 操作を支援するための API をいくつかご用意しています。Cisco API は文字列ライブラリに直接追加されますが、
スクリプトで SDP を操作するには、まず Lua SIP Message オブジェクトで提供される getSdp() API を使用して Lua SIP Message オブジェクトから SDP コンテンツ本文を取得する必要があります。その後は、スクリプト内で Cisco API に含まれる文字列ライブラリを使用して、SDP を操作できます。修正を終えたら、SIP Message オブジェクトに用意されている setSdp(sdp) API を使用して、SDP を SIP Message オブジェクトに書き戻します。これらの API の詳細については、次の 「SIP メッセージの API」 を参照してください。
-- 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
シスコからは、SDP を操作するという目的で、個々の行およびメディア記述全体の取得、修正、追加、挿入、削除を行う API を用意しています。この章の以降の部分では、これらの Cisco API について説明します。
SDP の任意の行を取得して操作するには、行を識別する手段が必要です。スクリプト作成者は、無効な SDP に影響できなければなりません。したがって、正規化のために SDP の構造を知っておくことが最低限必要です。無効な SDP に影響することは、不可能ではないにしても難しいです。有効な SDP を操作することも可能です。これらの目標を念頭に置いて、文字列ベースのアプローチが保証されています。
SDP を操作するための Lua API は、大きく分けると 2 つのカテゴリに分類されます。
• 「行レベルの API」 :この一連の API は、SDP 内の行を取得して操作できるようになっています。
• 「メディア記述レベルの API」 :この一連の API は、特定のメディア記述を操作するためのものです。
セッション レベルの行の操作には、行レベルの一連の API を使用し、メディア記述の操作には、メディア記述レベルの一連の API を使用します。
(注) 行を操作するために設計された一連の API の操作対象は、セッション レベルの行のみに限定されるわけではありません。
Cisco API より
次の行レベル Cisco API が使用可能です。
• 「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)
パラメータの説明
|
|
sdp |
sdp パラメータは、SDP の入った文字列です。制御文字(「\r」、「\n」 など)もすべて含みます。API は、sdp パラメータについて SDP 構造を一切強制しません。単なる文字列として扱います。スクリプト作成者は、SDP の一部分(たとえば、音声メディア記述など)を操作するのにこの API を使用できます。 |
start-of-line |
start-of-line パラメータは、sdp 内の行の開始を探すのに使用される文字列です。一般的なスクリプトでは、たとえば、「o=」、「a=rtpmap:9」などが sdp 内のこの文字列で始まる最初の行の取得/修正/挿入/削除に使用できます。この文字列で始まる行が複数存在する場合は、最初の行だけが操作対象となります。 このパラメータは、<char>=<string> という形式になっていなければなりません。つまり、2 文字目が必ず等号でなくてはなりません。このパラメータがこの形式になっていない場合は、「nil」が返されます。 |
line-contains |
line-contains は、「start-of-line」パラメータに指定した文字列で開始する行内で検索する、追加の一致条件として使用される文字列です。nil を指定した場合、 line-contains は一致条件として使用されません。その場合、 start-of-line パラメータだけが行の検索に使用されます。 line-contains が nil でなければ、 start-of-line と line-contains の両方が検索に使用されます。SDP 内に検索条件(両方)に一致する行が複数存在する場合は、最初の行だけが返されます。 このパラメータで指定するこの追加の一致条件が必要ない場合は、値として「nil」を引用符なしで渡す必要があります。 |
new-line |
new-line は、最終的な sdp(返された sdp)に追加/挿入する文字列です。 |
上記 API は、これらのパラメータを文字列として扱います。このため、セッション レベルの行とメディア レベルの行の両方を操作できます。行がセッション レベルかメディア レベルかに応じて動作が変わることは一切ありません。条件に一致する行を検索する際、各行は \n (または \r\n )で終わるものとします。
パラメータ内の文字はいずれも Lua の「マジック キャラクタ」とは見なされません。すべての文字が、特別な意味は一切持たず、プレーン文字として扱われます。
getLine
sdp:getLine(start-of-line, line-contains) returns string
このメソッドは、sdp 内の start-of-line で開始して文字列 line-contains を持つ最初の行を返します。
例:SDP から c 行を取得して、ローカル変数に値として格納します。
スクリプト
function M.outbound_INVITE(msg)
local ipv4_c_line = sdp:getLine("c=", "IP4")
メッセージ
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
出力/結果
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)
このメソッドは、「sdp」内で start-of-line で開始する行を探します。 line-contains パラメータが nil でない場合は、それもその行内に存在している必要があります。一致する行(行終了文字を含む)が、 new-line パラメータで置き換えられます。得られた sdp が返されます。
一致する行が見つからない場合は、元の sdp が未変更のまま返されます。
(注) SDP のルールに従うために、new-line には \r\n(または \n)で終了する文字列を指定することを推奨します。ユーティリティによって行終了文字が強制されることはありません。
例:次のコードは、a= 行の G.722 コーデックをドットのない G722 に変更します。
スクリプト
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)
メッセージ
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
出力/結果
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
このメソッドは、SDP の末尾に new-line を追加します。SDP のルールに従うために、 new-line には \r\n (または \n )で終了する文字列を指定することを推奨します。この API によって行終了文字が強制されることはありません。
例:SDP の末尾に属性行を追加します。
スクリプト
function M.outbound_INVITE(msg)
sdp = sdp:addLine("a=some-attribute\r\n")
メッセージ
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
出力/結果
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)
このメソッドは、sdp 内で start-of-line で開始し、なおかつ line-contains パラメータが指定されていればその行内に line-contains も持つ最初の行を探します。次に、見つかった行の後ろに new-line を挿入します。
例:SDP 内の「a=」および「G729」を持つ行の後ろに行を 1 つ挿入します。
スクリプト
function M.outbound_INVITE(msg)
sdp = sdp:insertLineAfter("a=", "G729", "a=ptime:30\r\n")
メッセージ
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
出力/結果
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)
このメソッドは、sdp 内で start-of-line で開始し、なおかつ line-contains パラメータが指定されていればその行内に line-contains も持つ最初の行を探します。次に、見つかった行の前に new-line を挿入します。
例:SDP 内の「s=」行の前に行を 1 つ挿入します。
スクリプト
function M.inbound_ANY_INVITE(msg)
sdp= sdp:insertLineBefore("s=", nil, "e=nobody@cisco.com\r\n")
メッセージ
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
出力/結果
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)
このメソッドは、「sdp」内で「start-of-line」で開始し、なおかつ「line-contains」パラメータが指定されていればその行内に「line-contains」も持つ最初の行を探します。一致した行は、sdp から削除されます。
例:「a=rtpmap」と「G729」の両方を含む行を SDP から削除します。
スクリプト
function M.inbound_INVITE(msg)
sdp = sdp:removeLine("a=rtpmap:", "G729")
メッセージ
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
出力/結果
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
getMediaDescription(media-level)
getMediaDescription(media-level) returns media-description
この API は、指定したメディア レベルの特定のメディア記述を取得するのに使用します。
例:最初のメディア記述を取得して、ローカル変数に値として格納します。
スクリプト
function M.outbound_INVITE(msg)
local m1 = sdp:getMediaDescription(1)
メッセージ
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
出力/結果
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
この API は、m 行に media-contains と完全に一致する部分を持つ特定のメディア記述を取得するのに使用します。
(注) 複数の m 行が一致する場合は、media-description と一致する最初のメディア記述だけが返されます。
例:m 行に「audio」というテキストを含む最初のメディア記述を取得して、ローカル変数に値として格納します。
スクリプト
function M.outbound_INVITE(msg)
local audio = sdp:getMediaDescription("audio")
メッセージ
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
出力/結果
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)
この API は、指定したメディア レベルの特定のメディア記述を修正するのに使用します。
例:「a=ptime:20\r\n」を含む業を音声メディア記述から削除します。
スクリプト
function M.outbound_INVITE(msg)
local m1 = sdp:getMediaDescription(1)
m1 = m1:gsub("a=ptime:20\r\n", "")
sdp = sdp:modifyMediaDescription(1, m1)
正規化前のメッセージ
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
正規化後のメッセージ
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)
この API は、m 行に media-contains と完全に一致する部分を持つ特定のメディア記述を修正するのに使用します。複数の m 行が一致する場合は、media-description と一致する最初のメディア記述だけが修正されます。
例:「a=ptime:20\r\n」を含む業を音声メディア記述から削除します。
スクリプト
function M.outbound_INVITE(msg)
local audio = sdp:getMediaDescription("audio")
audio = audio:gsub("a=ptime:20\r\n", "")
sdp = sdp:modifyMediaDescription("audio", audio)
正規化前のメッセージ
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
正規化後のメッセージ
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)
この API は、1 つのメディア記述を最後のメディア記述として追加するのに使用します。
例:
このスクリプトは、着信 INVITE からビデオ メディア記述を削除して、保存します。このスクリプトでは、ビデオ メディア記述が 2 つ目のメディア記述であることを前提としています。対応する発信応答については、このスクリプトは、格納されているビデオ メディア記述を取得し、ポートを 0 に設定し、そのメディア記述を発信 SDP に追加します。
スクリプト
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)
正規化前のメッセージ
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
正規化後のメッセージ
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)
この API は、指定したメディア レベルのメディア記述を追加するのに使用します。
例:メッセージ メディア記述を、それが SDP 内の最初のメディア記述になるように挿入します。
スクリプト
function M.outbound_INVITE(msg)
local message = "m=message 1234 sip:alice@10.10.10.100\r\n"
sdp = sdp:insertMediaDescription(1, message)
正規化前のメッセージ
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=- 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)
この API は、指定したメディア レベルのメディア記述を削除するのに使用します。
例:
「addMediaDescription(media-description)」 に示されている例を参照してください。この例は、removeMediaDescription も使用しています。
removeMediaDescription(media-contains)
removeMediaDescription(media-contains)
この API は、m 行に media-contains と完全に一致する部分を持つ特定のメディア記述を削除するのに使用します。
(注) 複数の m 行が一致する場合は、media-description と一致する最初のメディア記述だけが削除されます。
例:
このスクリプトは、着信 INVITE からビデオ メディア記述を削除して、保存します。対応する発信応答については、このスクリプトは、格納されているビデオ メディア記述を取得し、ポートを 0 に設定し、そのメディア記述を発信 SDP に追加します。
スクリプト
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)
正規化前のメッセージ
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
正規化後のメッセージ
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