opensip脚本的变量转换

本文详细介绍了OpenSIPS脚本中的Transformation功能,用于处理和操作变量,包括字符串、URI、Via头、参数表、Name-address、IP、CSV、SDP和正则表达式的转换。例如,通过{s.len}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.opensips.org/Documentation/Script-Tran-2-4

前言

        直观地说,Transformation 指的是作用于一个变量的函数(脚本变量、伪变量、AVP、静态字符串),从输入中获取特定的值。但不改变原输入值。

        下面是一个OpenSIPS 脚本实例,说明各种变量的用法:

# check if username in From header is equal with username in To header
if ($fU == $tU) {
   ...
}

# Request-URI username based processing
switch ($rU) {
   case "1234":
      ...
   break;
   case "5678":
      ...
   break;
   default:
     ...
}

# assign an integer value to an variable
$var(gw_count) = 1;

# assign a string value to an AVP
$avp(server) = "opensips";

# store the Request-URI in a variable
$var(ru_backup) = $ru;

# concat "sip:" + From username + "@" + To domain in a script variable x
$var(x) = "sip:" + $fU + "@" + $td;

        transformation旨在获取变量的各种属性值(比如值的长度、局部取值,取子串),或者计算其它转换值(比如说通过hexa编码、md5 、对DB操作的escape/unescape)。

        语法上,transformation出现在一对花括号 '{' '}' 之间,并且紧跟在变量名之后。使用transformation时,变量名和transformation必须用用一对括符 '()'限定。

       上实例:

# the length of From URI ($fu is pseudo-variable for From URI)
$(fu{s.len})

一个变量可以同时适配多个transformation。

# the length of escaped 'Test' header body
$(hdr(Test){s.escape.common}{s.len})

        除非有特别的定义,否则,所有transformation在处理出错时返回NULL(比如说,通过"{uri.param,name}" transformation查找一个不存在的URI参数)。此外,NULL输入是可接受的,这样就可以支持上一条transformation返回NULL的链式操作。

        任何地方都可以使用transformation,脚本变量支持,XLOG支持,AVP支持,甚至模块导出函数的参数中也支持,当然,表达式中的支持就更不在话下了。

重要提示:想进一步了解变量中是怎样使用transformation的话,请参考:https://www.opensips.org/Documentation/Script-CoreVar-2-2

 

1. 字符串Transformation

        这些transformation 的命名以字符's.'打头,它们的作用就是操作字符串变量。可用transformation 如下:

1.1 {s.len} 🔗

返回变量所存储字符串的长度。

$var(x) = "abc";
if($(var(x){s.len}) == 3)
{
   ...
}

1.2 {s.int} 🔗

把字符串转换为数字(整型),如果输入根本不包含数字信息,那么返回0。

$var(dur) = "2868.12 sec";
if ($(var(dur){s.int}) < 3600) {
  ...
}

1.3 {s.md5} 🔗

返回md5 Key

xlog("MD4 over From username: $(fU{s.md5})");

1.4 {s.substr,offset,length} 🔗

返回子串,子串以offset位置为起点,以参数length指定长度。如果offset为负数,那么从字符串的结尾处开始计数,-1为最后一个字符。offset为正数时, 0表示第一个字符。Length必须为正数,如果值为0,表示返回从offset到结束点的所有字符。offset和length可以是变量。

实例:

$var(x) = "abcd";
$(var(x){s.substr,1,0}) = "bcd"

1.5 {s.select,index,separator} 🔗

返回变量里的一个字段。字段以separator为分割符,以index为索引。separator 必须是一个字符,用作分割符。Index 必须为一个整数或变量。如果Index 值为负,那么表示从后往前索引,-1表示最后一个字段。如果Index 值为正数,索引0表示第一个字段。注意:如果某个字段为空,那么返回的是空值,不是NULL。

实例:

$var(x) = "12,34,56";
$(var(x){s.select,1,,}) => "34" ;

$var(x) = "12,34,56";
$(var(x){s.select,-2,,}) => "34"

1.6 {s.encode.hexa} 🔗

返回变量的hexa编码值。

1.7 {s.decode.hexa} 🔗

返回变量的hexa解码值。

1.8 {s.escape.common} 🔗

返回变量的转义串,被转义的字符有', ", 和0。在DB查询时非常有用,但如果使用的是非拉丁字符集,那么要注意。

1.9 {s.unescape.common} 🔗

上一条transformation的逆向操作。

1.10 {s.escape.user} 🔗

转义操作,把RFC规范中不允许出现在SIPURI里的字符,转换为 '%hexa'格式。

1.11 {s.unescape.user} 🔗

上一条transformation的逆向操作。

1.12 {s.escape.param} 🔗

转义操作,把RFC规范中不允许出现在SIPURI的参数中的字符,转换为 '%hexa'格式。

1.13 {s.unescape.param} 🔗

上一条transformation的逆向操作。

1.14 {s.tolower} 🔗

转换为小写的ASCII字符。

1.15 {s.toupper} 🔗

转换为大写的ASCII字符。

1.16 {s.index} 🔗

从第一个字符串的开始处查询另一个字符串。返回字符串起始处的索引,如果查询失败则返回NULL。有一个可选参数index,它指定开始查找位置的偏移量,支持负数。

$var(strtosearch) = 'onetwothreeone';
$var(str) = 'one';

# Search the string starting at 0 index
$(var(strtosearch){s.index, $var(str)}) # will return 0
$(var(strtosearch){s.index, $var(str), 0}) # Same as above
$(var(strtosearch){s.index, $var(str), 3}) # returns 11

# Negative offset
$(var(strtosearch){s.index, $var(str), -11}) # Same as above

# Negative wrapping offset
$(var(strtosearch){s.index, $var(str), -25}) # Same as above

#Test for existence of string in another
if ($(var(strtosearch){s.index, $var(str)}) != NULL)
    xlog("found $var(sstr) in $var(strtosearch)");

1.17 {s.rindex} 🔗

从第一个字符串的结尾处查询另一个字符串。返回字符串起始处的索引,如果查询失败则返回NULL。有一个可选参数index,它指定开始查找位置的偏移量,查找到的字符串必须在指定的偏移量位置之前,支持负数。

$(var(strtosearch){s.rindex, $var(str)}) # will return 11
$(var(strtosearch){s.rindex, $var(str), -3}) # will return 11
$(var(strtosearch){s.rindex, $var(str), 11}) # will return 11
$(var(strtosearch){s.rindex, $var(str), -4}) # will return 0

1.18 {s.fill.left, tok, len} 🔗

在字符串的左侧填充字符或字符串,直到len指定的长度填充满为止。如果原字符串的长度大于或等于len指定的值,那么返回原字符串(不截断)。

$var(in) = "485"; (also works for integer PVs)

$(var(in){s.fill.left, 0, 3})    => 485    
$(var(in){s.fill.left, 0, 6})    => 000485
$(var(in){s.fill.left, abc, 8})  => bcabc485

注意: 当前为了性能优化,不支持伪变量参数或小部件的"s.fill" 级联。

1.19 {s.fill.right, tok, len} 🔗

在字符串的右侧填充字符或字符串,直到len指定的长度填充满为止。如果原字符串的长度大于或等于len指定的值,那么返回原字符串(不截断)。如果输入变量是数值,会先转换为字符串

$var(in) = 485; (also works for string PVs)

$(var(in){s.fill.right, 0, 3})   => 485
$(var(in){s.fill.right, 0, 6})   => 485000
$(var(in){s.fill.right, abc, 8}) => 485abcab

1.20 {s.width, len} 🔗

指定长度为len,对输入进行截取或填充。填充时,以空字符为填料,填充在原字符串的右侧。同样,被截的内容也是右边的内容 。

$var(in) = "transformation";

$(var(in){s.width, 14})   => "transformation"
$(var(in){s.width, 16})  => "transformation  "
$(var(in){s.width, 9})   => "transform"

1.21 {s.trim} 🔗

删除输入内容的前导的空白字符,还有尾随的空白字符。空白字符包括:空格、制表符、换行符,回车符。

$var(in) = "\t \n input string  \r  ";
$(var(in){s.trim})   => "input string"

1.22 {s.trimr} 🔗

从输入字符串中删除任何尾随的空白字符。空白字符包括:空格、制表符、换行符,回车符。

$var(in) = "\t \n input string  \r  ";
$(var(in){s.trimr})   => "\t \n input string"

1.23 {s.triml} 🔗

从输入字符串中删除任何前导的空白字符。空白字符包括:空格、制表符、换行符,回车符。

$var(in) = "\t \n input string  \r  ";
$(var(in){s.triml})   => "input string  \r  "

1.24 {s.dec2hex} 🔗

把一个十进制数转换为十六进制数,输出描述为字符串。

1.25 {s.hex2dec} 🔗

把一个十六进制数转换为十进制数。

1.26 {s.b64encode} 🔗

把输入的二进制数据转换为ASCII字符串格式。

$var(in) = "\x2\x3\x4\x5!@#%^&*";
$(var(in){s.b64encode})   => "AgMEBSFAIyVeJio="

1.27 {s.b64decode} 🔗

假设输入是Base64字符串,尽可能地对它进行解码。

$var(in) = "AgMEBSFAIyVeJio=";
$(var(in){s.b64decode})   => "\x2\x3\x4\x5!@#%^&*"

1.28 {s.xor,secret} 🔗

根据两个字符串的长度,通过"secret"字符串对输出字符串执行一次或多次XOR逻辑运算。

$var(in) = "aaaaaabbbbbb";
$(var(in){s.xor,x})   => "!/>^P!/>^P!^U2^Q!^U2^Q"

2. URI Transformation

名字以 'uri.'打头的transformation。它们返回SIP URI的组件。如果指定的组件缺失,那么返回空字符串。

2.1 {uri.user} 🔗

返回URI里的USER组件。

2.2 {uri.host} 🔗

(和 {uri.domain}作用相同)

返回URI的domain组件。

2.3 {uri.passwd} 🔗

返回URI的password组件。

2.4 {uri.port} 🔗

返回URI的port

2.5 {uri.params} 🔗

以字符串形式返回所有的URI参数。

2.6 {uri.param,name} 🔗

返回name指定的URI参数。

2.7 {uri.headers} 🔗

返回URI header

2.8 {uri.transport} 🔗

返回URI的transport 参数

2.9 {uri.ttl} 🔗

返回URI的ttl参数。

2.10 {uri.uparam} 🔗

返回URI的user参数

2.11 {uri.maddr} 🔗

返回URI的maddr 参数.

2.12 {uri.method} 🔗

返回URI的method 参数.

2.13 {uri.lr} 🔗

返回URI的lr参数.

2.14 {uri.r2} 🔗

返回URI的r2参数.

2.15 {uri.schema} 🔗

返回URI的schema。

 

3. VIA Transformation

名字以'via.'打头的transformation。输入变量为SIP的Via头域。这些transformation返回via头域的组件(参考via_body结构体的定义)。如果请求的组件缺失,那么返回空字符串。如果输入的Via头域值为空,那么将导致执行失败。以下描述如果没有特别说明,那么transform的返回值都是字符串(不是整数)。

实例:

    $var(upstreamtransport) = $(hdr(Via)[1]{via.transport}{s.tolower});
    $var(upstreamip) = $(hdr(Via)[1]{via.param,received});
    $var(clientport) = $(hdr(Via)[-1]{via.param,rport});

3.1 {via.name} 🔗

返回 protocol-name ( RFC3261 BNF的描述),通常为SIP。

3.2 {via.version} 🔗

返回 protocol-version ( RFC3261 BNF的描述),通常是2.0.

3.3 {via.transport} 🔗

返回transport( RFC3261 BNF的描述)取值通常为: UDPTCPTLS。它描述的是消息的传输方式。

3.4 {via.host} 🔗

(和{via.domain}等效)

返回 sent-by ( RFC3261 BNF的描述)里的host。通常是请求发送方的IP地址,它标识对方在哪里等待接收应答消息。

3.5 {via.port} 🔗

返回 sent-by ( RFC3261 BNF的描述)里的port。通常是请求发送方的端口,它标识对方在哪里等待接收应答消息。这个transform返回的结果既是数字,也是字符串。

3.6 {via.comment} 🔗

与via头域关联的comment。via_body 结构体中有这个字段定义,但是RFC3261中并没有明确允许Via携带comments(第221页中有提及,但是BNF 里并没有说明)。comment是一段用括号括起的文本。

3.7 {via.params} 🔗

以字符串返回Via头域的所有参数( RFC3261 BNF里的via-param )。返回结果可以用 {param.*}这个transform。这几乎提取了除了host和port之外的所有内容。

3.8 {via.param,name} 🔗

返回name指定的Via参数。典型的参数包括 branchrport 和received。

3.9 {via.branch} 🔗

返回VIA头域中的branch参数

3.10 {via.received} 🔗

返回VIA头域中的received参数

3.11 {via.rport} 🔗

返回VIA头域中的rport 参数。

 

4. 参数表 Transformation

名字以"param."打头的transformation。输入的变量值的格式是一个格式化的字符串,格式:name1=value1;name2=value2;...这些transformation返回特定参数的值,或者指定索引返回参数名。

4.1 {param.value,name} 🔗

返回名为'name'的参数的值

"a=1;b=2;c=3"{param.value,c} = "3"

'name' 可以是一个变量

4.2 {param.exist,name} 🔗

如果名为name 的参数存在,那么返回1,否则返回0,与参数是否有值无关。同时返回字符串和数字。name 可以是一个变量。它可用于检测没有值的参数的存在。

"a=0;b=2;ob;c=3"{param.exist,ob};         # returns 1
"a=0;b=2;ob;c=3"{param.exist,a};          # returns 1
"a=0;b=2;ob;c=3"{param.exist,foo};        # returns 0

4.3 {param.valueat,index} 🔗

返回index位置的参数值(index从0开始)。

"a=1;b=2;c=3"{param.valueat,1} = "2"

'index' 可以是另一个参数

4.4 {param.name,index} 🔗

返回index位置的参数名

"a=1;b=2;c=3"{param.name,1} = "b"

4.5 {param.count} 🔗

返回参数的个数

"a=1;b=2;c=3"{param.count} = 3

5. Name-address Transformation

名字以'nameaddr.'打头的transformation。处理变量类型为'[display_name] uri'这样的。transformation返回特定的字段值。

5.1 {nameaddr.name} 🔗

返回display name

'"test" <sip:test@opensips.org>' {nameaddr.name} = "test"

5.2 {nameaddr.uri} 🔗

返回URI

'"test" <sip:test@opensips.org>' {nameaddr.uri} = sip:test@opensips.org

5.3 {nameaddr.len} 🔗

返回整个name-addr组件值的长度

5.4 {nameaddr.param,param_name} 🔗

返回参数表中,名为param_name的参数的值。

'"test" <sip:test@opensips.org>;tag=dat43h' {nameaddr.param,tag} = dat43h

5.5 {nameaddr.params} 🔗

返回完整的参数表,包括参数名和值。

'"test" <sip:test@opensips.org>;tag=dat43h;private=yes' {nameaddr.params} = "tag=dat43h;private=yes"

6. IP Transformation

名字以'ip.'打头的transformation。

6.1 {ip.pton} 🔗

返回二进制描述的IP

"192.468.2.434" {ip.pton} returns a 4 byte binary representation of the IP provided

6.2 {ip.ntop} 🔗

把二进制IP转换为点分十进制的字符串。

"192.468.2.434"{ip.pton}{ip.ntop} = "192.468.2.434"

6.3 {ip.isip} 🔗

判断输入是否为有效的 IPv4 或IPv6地址,是返回1,否则返回0。

"192.468.2.434" {ip.isip} = 1
"192.468.2.434.1" {ip.isip} = 0

6.4 {ip.family} 🔗

如果二进制IP是 IPv4 或IPv6,那么返回 INET 或INET6。

"192.468.2.434" {ip.pton}{ip.family} = "INET"

6.5 {ip.resolve} 🔗

返回域名解析得出的IP地址。如果输入是个IP,那么Transformation不生效。

"opensips.org" {ip.resolve} = "78.46.64.50"

7. CSV Transformation

名字以"csv."打头的transformation。变量值为CSV格式:"field1,field2,..."。它返回字段的计数,或指定位置的字段值。

7.1 {csv.count} 🔗

返回指定CSV串里的实体数量:

"a,b,c" {csv.count} = 3

7.2 {csv.value} 🔗

返回指定位置的字段值。索引以0开始:

"a,b,c" {csv.value,2} = c

8. SDP Transformation

名字以"sdp."打头的transformation。变量的值为合法的SDP消息。它返回SDP消息里的指定行。

细分如下:

8.1 {sdp.line} 🔗

返回SDP的指定行。这个transformation还可以接收第二个参数,它指定第一个参数从SDP里取出多个值时的行号。索引以0开始。如果缺少第二个参数,那么取缺省值0。实例:

if (is_method("INVITE"))
   {
      $var(aline) = $(rb{sdp.line,a,1});
      xlog("The second a line in the SDP body is $var(aline)\n");
   }

if (is_method("INVITE"))
   {
      $var(mline) = $(rb{sdp.line,m});
      xlog("The first m line in the SDP body is $var(mline)\n");
   }

9.正则表达式Transformation

名字以"re."打头的transformation。输入可以是任意字符串。

9.1 {re.subst,reg_exp} 🔗

reg_exp参数可以是纯文本,也可以是变量。reg_exp的格式如下:

    /posix_match_expression/replacement_expression/flags

其中flag的取值及含义如下:

    i - 匹配时忽略大小写
    s - 多行匹配
    g - 替换所有匹配的值

实例:

$var(reg_input)="abc";
$var(reg) = "/a/A/g";
xlog("Applying reg exp $var(reg) to $var(reg_input) : $(var(reg_input){re.subst,$var(reg)})\n");

...
...
xlog("Applying reg /b/B/g to $var(reg_input) : $(var(reg_input){re.subst,/b/B/g})\n");

10. 实例

对一个变量,可以同时执行多个transformation,执行顺序从左到右。

  • 取参数中位置索引1的值的长度(注意位置索引,0表示第一个,1是第二个)。
$var(x) = "a=1;b=22;c=333";
$(var(x){param.value,$(var(x){param.name,1})}{s.len}) = 2
  • 判断是不是un-registration 消息
if(is_method("REGISTER") && is_present_hf("Expires") && $(hdr(Expires){s.int})==0)
    xlog("This is an un-registration");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值