Header Manipulation Rules for SDP
The Oracle Enterprise Communications Broker supports SIP header and parameter manipulation rules for four types of SIP message contents:
- headers
- elements within headers
- ASCII-encoded Multipurpose Internet Mail Extensions (MIME) bodies
- binary-encoded MIME ISDN User Part (ISUP) bodies
While Session Description Protocol (SDP) offers and answers can be manipulated in a fashion similar to ASCII-encoded MIME, such manipulation is primitive in that it lacks the ability to operate at the SDP session- and media-levels.
In addition, the system supports a variant of Header Manipulation Rules (HMR) operating on ASCII-encoded SDP bodies, with specific element types for descriptors at both the session-level and media-level, and the ability to apply similar logic to SDP message parts as is done for SIP header elements.
The configuration object, mime-sdp-rules, under sip-manipulation specifically addresses the manipulation of SDP parts in SIP messages. Just as existing header-rules are used to manipulate specific headers of a SIP message, mime-sdp-rules will be used to manipulate the SDP specific mime-attachment of a SIP message.
SDP Manipulation
mime-sdp-rules function in a similar fashion as header-rules. They provide
- parameters used to match against specific SIP methods and/or message types
- parameters used to match and manipulate all or specified parts of an SDP offer or answer
- a means of comparing search strings or expressions against the entire SDP
- different action types to allow varying forms of manipulation
Since only a single SDP can exist within a SIP message, users need not specify a content-type parameter as is necessary for a mime-rule. A mime-sdp-rule operates on the single SDP within the SIP message. If no SDP exists with the message, one can be added. If the message already contains a mime attachment, adding SDP results in a multipart message.
All manipulations performed against all or parts of the SDP are treated as UTF-8 ASCII encoded text. At the parent-level (mime-sdp-rule) the match-value and new-value parameters execute against the entire SDP as a single string.
An add action only succeeds in the absence of SDP because a message is allowed only a single SDP offer or answer. A delete operation at the mime-sdp-rule level will remove the SDP entirely.
Note that on an inbound sip-manipulation, SDP manipulations interact with the Oracle Enterprise Communications Broker codec-policy. SDP manipulations also interact with codec reordering and media setup. It is very possible to make changes to the SDP such that the call can not be setup due to invalid media parameters, or settings that will affect the ability to transcode the call. Consequently, user manipulation of the SDP can prove risky, and should be approached with appropriate caution.
Three configuration-objects, sdp-session-rule, sdp-media-rule, and mime-header-rule, exist under the mime-sdp-rule. These objects provide finer grained control of manipulating parts of the SDP.
sdp-session-rule
An sdp-session-rule groups all SDP descriptors, up until the first media line, into a single entity, thus allowing the user to perform manipulation operations on a session-specific portion of the SDP.
Like the mime-sdp-rule, all match-value and new-value operations performed at this level are executed against the entire session group as a complete string. Given the sample SDP below, if an sdp-session-rule is configured, the match-value and new-values operate only on the designated portion.
v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 a=recvonly m=audio 49170 RTP/AVP 0 m=video 51372 RTP/AVP 31 m=application 32416 udp wb a=orient:portrait
Nested under the sdp-session-rule configuration object is an sdp-line-rule object, the object that identifies individual descriptors within the SDP. The types of descriptors used at the sdp-session-rule level are v, o, s, i, u, e, p, c, b, t, r, z, k, and a, the descriptors specific to the entire session description.
This level of granularity affords the user a very simple way to making subtle changes to the session portion of the SDP. For instance, it is very common to have to change the connection line at the session level.
The add and delete actions perform no operation at the sdp-session-rule level.
sdp-media-rule
An sdp-media-rule groups all of the descriptors that are associated with a specific media-type into single entity, thus allowing the user to perform manipulation operations on a media-specific portion of the SDP. For example, a user can construct an sdp-media-rule to change an attribute of the audio media type.
Like a mime-sdp-rule, all match-value and new-value operations performed at this level are executed against the entire media-group as a complete string. Given the sample SDP below, if a media-level-descriptor is configured to operate against the application group, the match-value and new-values would operate only on designated portion.
v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 a=recvonly m=audio 49170 RTP/AVP 0 m=video 51372 RTP/AVP 31 m=application 32416 udp wb a=orient:portrait
A configuration parameter media-type is used to specify the media group on which to operate. It contains all of the descriptors including the m-line up to the next m-line. This parameter is a string field and must match the media-type exactly as it appears within the SDP. The special media-type media can be used to refer to all media types. This is particularly useful when performing an add operation, when the user wants to add a media section between the first and second medias, but does not know what media type they are. Otherwise, during an add operation, the media section would be added before the specified media-type (if no index parameter was provided).
The types of descriptors used at the sdp-media-rule level are m, i, c, b, k, and a, the descriptors specific to the media description.
This level of granularity affords the user a very simple way to making subtle changes to the media portion of the SDP. For instance, it is very common to have to change the name of an audio format (for example G729 converted to g729b), or to add attributes specific to a certain media-type.
The index operator is supported for the media-type parameter (for example, media-type audio[1]). Like header rules, if no index is supplied, this means operate on all media-types that match the given name. For specifying specific media-types, the non-discrete indices are also supported (for example, ^ - last). Adding a media-type, without any index supplied indicates that the media should be added at the beginning. The special media-type media uses the index as an absolute index to all media sections, while a specific media-type will index relative to that given media type.
For sdp-media-rules set to an action of add where the media-type is set to media, the actual media type is obtained from the new-value, or more specifically, the string after m= and before the first space.
Given the following SDP:
v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 m=audio 49170 RTP/AVP 0 m=audio 48324 RTP/AVP 8 m=video 51372 RTP/AVP 31
With the sdp-media-rule:
sdp-media-rule name smr media-type audio[1] action manipulate comparison-type case-sensitive match-value new-value "m=audio 1234 RTP/AVP 8 16"
This rule operates on the 2nd audio line, changing the port and adding another codec, resulting in the SDP:
v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 m=audio 49170 RTP/AVP 0 m=audio 1234 RTP/AVP 8 16 m=video 51372 RTP/AVP 31
The following rule, however:
sdp-media-rule name smr media-type media[1] action add comparison-type case-sensitive match-value new-value "m=video 1234 RTP/AVP 45"
adds a new video media-type at the 2nd position of all media-lines, resulting in the SDP:
v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 m=audio 49170 RTP/AVP 0 m=video 1234 RTP/AVP 45 m=audio 48324 RTP/AVP 8 m=video 51372 RTP/AVP 31
sdp-line-rule
Unlike header-rules, sdp descriptors are not added in the order in which they are configured. Instead they are added to the SDP adhering to the grammar defined by RFC 4566 (as is shown below).
Session description v= (protocol version) o= (originator and session identifier) s= (session name) i=* (session information) u=* (URI of description) e=* (email address) p=* (phone number) c=* (connection information -- not required if included in all media) b=* (zero or more bandwidth information lines) One or more time descriptions ("t=" and "r=" lines; see below) z=* (time zone adjustments) k=* (encryption key) a=* (zero or more session attribute lines) Zero or more media descriptions (see below) Time description t= (time the session is active) r=* (zero or more repeat times) Media description, if present m= (media name and transport address) i=* (media title) c=* (connection information -- optional if included at session level) b=* (zero or more bandwidth information lines) k=* (encryption key) a=* (zero or more media attribute lines)
* after the equal sign denotes an optional descriptor.
This hierarchy is enforced meaning that if you configure a rule which adds a session name descriptor followed by a rule which adds a version descriptor, the SDP will be created with the version descriptor first, followed by the session name.
The only validation that will occur is the prevention of adding duplicate values. In much the same way that header-rules prevents the user from adding multiple To headers, the descriptor rule will not allow the user to add multiple descriptors; unless multiple descriptors are allowed, as is in the case of b, t, r and a.
There exists a parameter type under the sdp-line-rule object that allows the user to specify the specific line on which to perform the operation. For example: v, o, s, i, u, e, p, c, b, t, r, z, k, a, and m. Details on these types can be found in RFC 4566.
For those descriptors, of which there may exist zero or more (b, t, r, and a) entries, indexing grammar may be used to reference the specific instance of that attribute. This indexing grammar is consistent with that of header-rules for referring to multiple headers of the same type.
Given the example SDP below:
v=0 o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4 s=SDP Seminar i=A Seminar on the session description protocol u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps e=mjh@isi.edu (Mark Handley) c=IN IP4 224.2.17.12/127 t=2873397496 2873404696 r=604800 3600 0 90000 r=7d 1h 0 25h a=recvonly m=audio 49170 RTP/AVP 0 m=video 51372 RTP/AVP 31 m=application 32416 udp wb a=orient:portrait
and the following sdp-line-rule:
sdp-line-rule name removeRepeatInterval type r[1] action delete
The rule removeRepeatInterval removes the second repeat interval descriptor within the SDP.
The behavior of all SDP rules follow the same behavior of all manipulation rules in that they are executed in the order in which they are configured and that each rule executes on the resultant of the previous rule.
Each descriptor follows its own grammar and rules depending on the type specified. The values of the descriptor are evaluated at runtime since the new-values themselves are evaluated at runtime. At this time no validation of the grammar for each of the types is performed. The user is responsible for properly formatting each of the descriptors according to their specifications.
For instance, the version (v) descriptor can be removed from the SDP but leaving all descriptors for that SDP, causing the SDP to become invalid. This is consistent with the way header-rules operate, in that there is no validation for the specific headers once they have been manipulated through HMR.
Regular Expression Interpolation
An interpolated regular expression is a regular expression that is compiled and evaluated at runtime. Today all regular expressions are compiled at configuration time in order to improve performance. There are cases where a regular expression is determined dynamically from data within a SIP message. In these circumstances the regular expression is unknown until the time of execution.
In order to have a regular expression be interpolated at runtime, it must be contained within a set of {}. An interpolated expression can have any number of regular expressions and strings appended together. Any characters to the left or right of the curly braces will be appended to the value within the curly braces. The curly braces are effectively two operators treated as one (interpolate the value contained within and then concatenate the values to the left and right of the curly braces). If the comparison-type is set to pattern-rule and the match-value contains a value that matches the grammar below, then it will be treated as an interpolated expression.
([^\\]|^)\{\$[^0-9]+[^}]*\}
The example below demonstrates using a user defined variable within a regular expression of another rule at runtime.
element-rule name someRule type header-value action replace comparison-type pattern-rule match-value ^sip:{$rule1.$0}@(.+)$ new-value sip:bob@company.com
If the value of $rule1.$0 evaluates to alice then it will successfully match against the string sip:alice@comcast.net. An interpolated expression can be as simple as “{$rule1.$0}” or as complex as ^sip:{rule1.$0}@{$rule2[1].$2}$. It is not possible to interpolate a normal regular expression since the grammar will not allow the user to enter such an expression. Only variables can be contained with the curly braces.
The resultant of interpolated expressions can be stored in user defined variables. Given the same example from above, if the rule someRule was referenced by another rule, the value of sip:alice@comcast.net would be stored within that rule.
Interpolation only makes a single pass at interpolation, but does so every time the Rule executes. In other words, if the Rule is applied to the Route header, it will interpolate again for each Route header instance. What this means is that the value within the curly braces will only be evaluated once. For instance, if the value {$someRule.$1} evaluates to {$foobar.$2} the Oracle Enterprise Communications Broker (OECB) will treat $foobar.$2 as a literal string which it will compile as a regular expression. The OECB will not recursively attempt to evaluate $foobar.$2, even if it was a valid user defined variable.
Interpolated regular expressions will evaluate to TRUE if an only if both the regular expression itself can be compiled and it successfully matches against the compared string.
Regular Expressions as Boolean Expressions
Regular expressions can be used as boolean expressions today if they are the only value being compared against a string, as is shown in the case below.
mime-rule name someMimeRule content-type application/text action replace comparison-type pattern-rule match-value ^every good boy .* new-value every good girl does fine However, regular expressions can not be used in conjunction with other boolean expressions to form more complex boolean expressions, as is shown below. mime-rule name someMimeRule content-type application/text action replace comparison-type boolean match-value $someRule & ^every good boy .* new-value every good girl does fine
There are many cases where the user has the need to compare some value as a regular expression in conjunction with another stored value. It is possible to perform this behavior today, however it requires an extra step in first storing the value with the regular expression, followed by another Manipulation Rule which compares the two boolean expressions together (e.g. $someRule & $someMimeRule).
In order to simplify the configuration of some sip-manipulations and to make them more efficient this functionality is being added.
Unfortunately, it is not possible to just use the example as is shown above. The problem is there are many characters that are commonly used in regular expressions that would confuse the HMR expression parser (such as $, and +). Therefore delimiting characters need to be used to separate the regular expression from the other parts of the expression.
To treat a regular expression as a boolean expression, it needs to be enclosed within the value $REGEX(<expression>,<compare_string>=$ORIGINAL); where <expression> is the regular expression to be evaluated. <compare_string> is the string to compare against the regular expression. This second argument to the function is defaulted to $ORIGINAL which is the value of the of the specific Manipulation Rule object. It can be overridden to be any other value the user desires.
The proper configuration for the example above to use regular expressions as boolean expressions is
mime-rule name someMimeRule content-type application/text action replace comparison-type boolean match-value $someRule & $REGEX(“^every good boy .*”) new-value every good girl does fine
It is also possible to use expressions as arguments to the $REGEX function. These expressions will in turn be evaluated prior to executing the $REGEX function. A more complex example is illustrated below.
header-rule name checkPAU header-name request-uri action reject comparison-type boolean match-value (!$REGEX($rule1[0],$FROM_USER))& (!$REGEX($rule2[0],$PAI_USER)) msg-type request new-value 403:Forbidden methods INVITE,SUBSCRIBE,MESSAGE,PUBLISH, OPTIONS, REFER
It should be noted that when using $REGEX() in a boolean expression, the result of that expression is not stored in the user variable. The comparison-type must be set to pattern-rule in order to store the result of a regular expression.
The arguments to the $REGEX() function are interpolated by default. This is the case since the arguments themselves must be evaluated at runtime. The following example is also valid.
mime-rule name someMimeRule content-type application/text action replace comparison-type boolean match-value $someRule & $REGEX(“^every good {$rule1[0].$0} .*”)
Moving Manipulation Rules
You can move rules within any manipulation-rule container. Any manipulation rule that contains sub-rules offers the ACLI command move <from index> <to index>. For example, given the order and list of rules below:
1. rule1
2. rule2
3. rule3
4. rule4
You can move rule3 to position 1 by executing move 3 1. The resulting order is: rule3, rule1, rule2, rule4. A move operation causes a shift (or insert before) for all other rules. When you move a rule from the top or middle to the bottom, the system shifts all rules above the bottom up to the position of the rule that you moved. When you move a rule from the bottom or middle to the top, the system shifts all rules below down to the position of the rule that you moved. Positions start from 1.
A valid from-index and to-index are required to be supplied as arguments to the move action. If you enter a range that is out of bounds for either the from-index or to-index, the ACLI informs you that the command did not execute and the reason.
If you create an invalid sip-manipulation by incorrectly ordering the manipulation rules, the Oracle Enterprise Communications Broker validates the rules at configuration time and treats them as invalid prior to runtime. This may or may not affect the outcome of the sip-manipulation as a configured rule may not perform any operation if it refers to a rule that has yet to be executed. It is your responsibility to reorder the remaining rules in order to make the sip-manipulation valid again.
Note that rules of a different type at the same level are all part of the same list. Header-rules, mime-rules, mime-isup-rules, and mime-sdp-rules all share the same configuration level under sip-manipulation. When selecting a move from-index and to-index for a header-rule, you must take into consideration the location of all other rules at the same level because the move is relative to all rules at that level. The move is not relative to the particular rule you selected (for example, the header-rule).
Because the list of rules at any one level can be lengthy, you can issue the move command one argument at a time, providing you with the ability to select indices. For example, typing move without any arguments displays the list of all the rules at that level. After selecting an appropriate index, the system prompts you with a to-index location based on the same list provided.
For Example:
ORACLE(sip-mime-sdp-rules)# move select a rule to move
1: msr sdp-type=any; action=none; match-value=; msg-type=any
2: addFoo header-name=Foo; action=none; match-value=; msg-type=any
3: addBar header-name=Bar; action=none; match-value=; msg-type=any
selection: 2 destination: 1 Rule moved from position 2 to position 1 ACMEPACKET(sip-mime-sdp-rules)#
Rule Nesting and Management
There will be cases where the user wants to take a stored value from the SDP and place it in a SIP header, and vice-versa. All header-rules, element-rules, mime-rules, mime-isup-rules, isup-param-rules, mime-header-rules and mime-sdp-rules are inherited from a Manipulation Rule. A Sip Manipulation is of type Manipulation which contains a list of Manipulation Rules. Each Manipulation Rule can itself contain a list of Manipulation Rules. Therefore when configuring manipulation rules, they will be saved in the order which they have been configured. This is different from the way other configuration objects are configured. Essentially, the user has the option of configuring which type of object they want and when they are done, it gets added to the end of the sip-manipulation, such that order is preserved. This will mean that any Manipulation Rule at the same level can not share the same name. For example, names of header-rules can’t be the same as any of the mime-sdp-rule ones or mime-isup-rule. This allows the user to reference stored values from one rule type in another at the same level.
ACLI Configuration Examples
The following eight sections provide sample SDP manipulations.
Remove SDP
sip-manipulation name stripSdp description remove SDP from SIP message mime-sdp-rule name sdpStrip msg-type request methods INVITE action delete comparison-type case-sensitive match-value new-value
Remove Video from SDP
sip-manipulation name stripVideo description strip video codecs from SIP message mime-sdp-rule name stripVideo msg-type request methods INVITE action manipulate comparison-type case-sensitive match-value new-value sdp-media-rule name removeVideo media-type video action delete comparison-type case-sensitive match-value new-value
Add SDP
sip-manipulation name addSdp description add an entire SDP if one does not exist mime-sdp-rule name addSdp msg-type request methods INVITE action add comparison-type case-sensitive match-value new-value “v=0\r\no=mhandley 2890844526 2890842807 IN IP4 “+$LOCAL_IP+”\r\ns=SDP Seminar\r\ni=A Seminar on the session description protocol\r\nu=http: //www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps\r\ne=mjh@isi.edu (Mark Handley)\r\nc=IN IP4 “+$LOCAL_IP+”\r\nt=2873397496 2873404696\r\na=recvonly\r\nm=audio 49170 RTP/AVP 0\r\n”
Manipulate Contacts
This rule changes the contact in the SDP to the value contained in the Contact header.
sip-manipulation name changeSdpContact description changes the contact in the SDP to the value of the contact header header-rule name storeContact header-name Contact action store comparison-type pattern-rule msg-type request methods INVITE match-value new-value element-rule name storeHost parameter-name type uri-host action store match-val-type ip comparison-type pattern-rule match-value new-value mime-sdp-rule name changeConnection msg-type request methods INVITE action manipulate comparison-type case-sensitive match-value new-value sdp-session-rule name changeCLine action manipulate comparison-type case-sensitive match-value new-value sdp-line-rule name updateConnection type c action replace comparison-type case-sensitive match-value $storeContact.$storeHost new-value $storeContact.$storeHost.$0
Remove a Codec
This rule changes the contact in the SDP to the value contained in the Contact header.
sip-manipulation name removeCodec description remove G711 codec if it exists mime-sdp-rule name removeCodec msg-type request methods INVITE action manipulate comparison-type case-sensitive match-value new-value sdp-media-rule name removeG711 media-type audio action manipulate comparison-type case-sensitive match-value new-value sdp-line-rule name remove711 type m action replace comparison-type pattern-rule match-value ^(audio [0-9] {1,5} RTP.*)( [07] \b)(.*)$ new-value $1+$3 sdp-line-rule name stripAttr type a action delete comparison-type pattern-rule match-value ^(rtpmap|fmtp): [07]\b$ new-value
Change Codec
sip-manipulation name convertCodec description changeG711toG729 mime-sdp-rule name changeCodec msg-type request methods INVITE action manipulate comparison-type case-sensitive match-value new-value sdp-media-rule name change711to729 media-type audio action manipulate comparison-type case-sensitive match-value new-value sdp-line-rule name change711 type m action replace comparison-type pattern-rule match-value ^(audio [0-9]{4,5} RTP/AVP.*)( 0)(.*)$ new-value $1+” 18”+$3 sdp-line-rule name stripAttr type a action delete comparison-type pattern-rule match-value ^rtpmap:0 PCMU/ .+$ new-value sdp-line-rule name addAttr type a action add comparison-type boolean match-value $change711to729. $stripAttr new-value rtpmap:18 G729/8000
Remove Last Codec and Change Port
sip-manipulation name removeLastCodec description remove the last codec mime-sdp-rule name removeLastCodec msg-type request methods INVITE action manipulate comparison-type case-sensitive match-value new-value sdp-media-rule name removeLast media-type audio action manipulate comparison-type case-sensitive match-value new-value sdp-line-rule name isLastCodec type m action store comparison-type pattern-rule match-value ^(audio )([0-9]{4, 5})( RTP/AVP [0-9]{1-3})$ new-value sdp-line-rule name changePort type m action replace comparison-type boolean match-value $removeLastCodec. $removeLast.$isLastCodec new-value $removeLastCodec. $removeLast.$isLastCodec.$1+0+$removeLastCodec.$removeLast. $isLastCodec.$3
Remove Codec with Dynamic Payload
sip-manipulation name removeAMR description remove the AMR and AMR-WB dynamic codecs mime-sdp-rule name sdpAMR msg-type request methods INVITE action manipulate comparison-type case-sensitive match-value new-value sdp-media-rule name mediaAMR media-type audio action manipulate comparison-type case-sensitive match-value new-value sdp-line-rule name isAMR type a action delete comparison-type pattern-rule match-value ^rtpmap:([0-9] {2,3}) AMR new-value sdp-media-rule name mediaIsAMR media-type audio action manipulate comparison-type boolean match-value $sdpAMR.$media AMR.$isAMR new-value sdp-line-rule name delFmtpAMR type a action delete comparison-type pattern-rule match-value ^fmtp:{$sdpAMR. $mediaAMR. $isAMR.$1}\b new-value sdp-line-rule name delAMRcodec type m action find-replace-all comparison-type pattern-rule match-value ^audio [0-9]+ RTP.*( {$sdpAMR. $mediaAMR.$isAMR.