斯是陋室,惟吾德馨

除了技术,还有更多值得关注……

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Chapter 4. Getting Started What is SIP and how does it work?  SIP简介及工作原理

arden免责瞎翻译http://blog.csdn.net/arden1019

原文地址http://siprouter.onsip.org/doc/gettingstarted/ch04.html

Table of Contents目录

SER Architecture and ser.cfg SER构架及ser.cfg

Core and Modules 核心和模块

ser.cfgs Seven Sections ser.cfg 的七个部分

Transactions, Dialogs, and Sessions 事务,会话和会议

Understanding Message Processing in ser.cfg 理解ser.xfg中的消息处理

Stateful vs. stateless

Understanding SIP and RTP 理解SIPRTP

Back-end applications and B2BUA 后台程序和B2BUA

NAT, STUN, and RTP proxy  

Registration behind NAT NAT后面的注册

INVITEs behind NAT     NAT后面的邀请

STUN

Other non-ser NAT traversal techniques 其它非SERNAT穿透技术

URI, R-URI, and Branches

SER Architecture and ser.cfg SER构架及ser.cfg

Core and Modules核心和模块

SER is built around a processing core that receives SIP messages and enables the basic functionality of handling SIP messages. Most of SERs functionality is offered through its modules, much like the Apache web server. By having a modular architecture, SER is able to have a core that is very small, fast, and stable. SER modules expose functionality that can be utilized in the SER configuration file, ser.cfg. The ser.cfg configuration file controls which modules shall be loaded and defines how the modules shall behave by setting module variables. You can think of the ser.cfg file as the brains of the SIP router.

SER处理核心接收SIP消息并提供基本的SIP消息控制功能。类似于Apache,大多数SER功能由它的模块来提供。介于这样模块化的构架,SER拥有一个小巧、快速、稳定的核心。SER的配置文件可以利用模块提供的功能。Ser.cfg配置文件控制模块的加载并定义给模块传递什么参数。你可以理解为ser.cfg就像SIP路由器的大脑。

ser.cfgs Seven Sections ser.cfg 的七个部分

ser.cfg has seven main logical sections: ser.cfg有七个主要的逻辑段。

1.      Global Definitions Section. This portion of ser.cfg usually contains the IP address and port to listen on, debug level, etc. Settings in this section affect the SER daemon itself; 全局定义段:ser.cfg的这部分通常包含IP地址,监听端口,调试版本等等。对此段所作的设置将影响到SER后台程序本身。

2.      Modules Section. This section contains a list of external libraries that are needed to expose functionality not provided by the core as noted above. These modules are shared object .so files and are loaded with the loadmodule command; 模块段。此段包含了一个外部库列表。这些库提供了上面说的核心没有的额外功能。这些模块为共享库(.so文件),使用loadmodule命令加载。

3.      Module Configuration Section. Many of the external libraries specified in the Modules Section need to have parameters set for the module to function properly. These module parameters are set by use of the modparam command, which takes this form: 模块配置段。模块段指定的很多外部库需要设置合适的参数。使用modparam命令来设置这些参数,语法如下:

modparam(module_name, module_parameter, parameter_value)

4.      Main Route Block. The main route block is analogous to a C programs main function. This is the entry point of processing a SIP message and controls how each received message is handled;主要路由块。它类似于C程序中的main函数,这是处理一个SIP消息的入口,它控制每一个接收到的消息如何处理。

5.      Secondary Route Blocks. In addition to the main route block, ser.cfg may contain additional route blocks that can be called from the main route block or from other secondary route blocks. A secondary route block is analogous to a subroutine; 二级路由块。添加于主要路由块。Ser.cfg 可以包含附加的路由模块,它在主要路由模块中被调用。一个二级路由模块类似于一个子程序。

6.      Reply Route Block. Optional reply route blocks may be utilized to handle replies to SIP messages. Most often these are OK messages;回复路由模块。可选择的回复路由模块可以提供对SIP消息回复的路由控制。大多数都是OK消息。

7.      Failure Route Block. Optional failure route blocks may be used when special processing is needed to handle failure conditions such as a busy or timeout; 失败路由块。可选择的失败路由模块可以用于在失败情况下(如忙或超时)提供特殊的处理。

It is important to understand the SIP protocol and the various types of messages that are used in SIP signalling. Of course, by following the instructions in this document, you will get a working setup. However, before starting to tweak and adapt to your needs, we recommend that you do yourself a favour and read up on SIP. Please refer to http://www.iptel.org/ser/doc/sip_intro/sip_introduction.html as a good introduction. http://www.iptel.org/sip/siptutorial.pdf provides more depth. The official SIP RFC can be found at http://www.ietf.org/rfc/rfc3261.txt for those interested. 理解SIP协议很重要。很多类型的消息用于SIP信号传输。当然,通过本文的介绍,你可以开始工作。但需要对其做定制时,我们建议你最好先去了解一下SIPhttp://www.iptel.org/ser/doc/sip_intro/sip_introduction.html是一个不错的介绍,http://www.iptel.org/sip/siptutorial.pdf 提供了更深入的话题。官方SIP RFC可以从下面连接得到:http://www.ietf.org/rfc/rfc3261.txt

Transactions, Dialogs, and Sessions 事务,会话和会议

In order to understand ser.cfg properly, you need to understand three SIP concepts:为了完全地理解ser.cfg,你需要理解这三个SIP概念:

1.      SIP transaction: A SIP message (and any resends) and its direct (most often immediate) response (ex. User agent sends REGISTER to SER and receives OK);一条SIP消息和它的回应

2.      SIP dialog: A relationship between (at least) two SIP phones that exists for some time (ex. Dialog is established with an INVITE message and ended by a BYE message);SIP会话:两个SIP电话之间的某一时刻存在的关系。

3.      Session: An actual media stream of audio between the SIP phones; 两个SIP电话之间真正的语音流。

These concepts are hard to understand and you may want to revisit this section when you have read later sections or studied the ser.cfg in this document. The concepts are used in the sections below to explain some things commonly confused.这些概念不好理解,在你阅读后面章节或学习ser.cfg时,可能需要重新来回顾这些内容。这些概念用于解释一些通常混淆的事情。

NOTE: If you look at a SIP message, you can identify messages in a particular SIP transaction by looking at the Cseq number in the header. Each SIP dialog will have a Call-Id header (as well as one ID called a tag for each peer in the dialog) 注:如果你查看一条SIP消息,你可以从头部的Cseq数来识别出SIP消息为什么处理事务。每一个SIP会话将包含一个Call-Id 头。(在会话中的每一方,ID也被叫做标签(tag)

Understanding Message Processing in ser.cfg理解ser.xfg中的消息处理

You can think of ser.cfg as a script that is executed every time a new SIP message is received. For example, a user agent (UA) (Johns SIP phone) wanting to INVITE another UA (Joans SIP phone) to a conversation (John makes a call to Joan). John sends an INVITE SIP message to SER and ser.cfgs main route{} block will start at the top and execute through the commands found there.你可以把ser.cfg理解为一个脚本,每当收到一条新的SIP消息,它就执行一次。比方说一个UA(约翰的SIP电话)想要邀请另一个UA(琼的SIP电话)进行交谈。约翰发送一条INVITE消息到SERser.cfgmain route模块将从头开始执行。

The processing continues until it reaches a point where processing is finished and a decision is made whether to send the INVITE to Joan (using the t_relay() command), to send John a reply with an error (using sl_send_reply()), or just drop the whole INVITE (by reaching the end of the main route or break;), which, of course, is not recommended.程序继续处理直到它完成处理并决定 发送INVITE到琼(使用t_relay() 命令)还是发送一个错误消息给约翰(使用sl_send_reply()命令),或者只是丢弃掉整个INVITE(到达toute模块末或者一个break)--当然,这是不推荐的做法。

Joan will answer the INVITE with an OK message. The OK is a direct response to the initial INVITE and this message is handled by the last section in an on_reply_route[x]. If Joan didnt respond, or responded with an error (busy, etc), the failure_route[x] is called.琼将回复INVITE一个OK消息。OK直接答复最初的INVITE,这个消息被最后一段中的on_reply_route[x]控制。如果琼不回复或者回复一个错误(比如busy)failure_route[x]将被调用。(译注:请参考上面 ser.cfg seven sections)

Finally, John will send an ACK to tell Joan that everything was received and accepted.最后,约翰将发送一个ACK来告诉琼所有东西都收到并接受了。

NOTE 1: The described behaviour is dependent on using t_relay() in ser.cfg. Your SER is then said to be transaction stateful (see also next section)

1:所描述的行为依赖于ser.cfgt_reply()的使用。你的SER应该为transaction stateful(请参考下一段)

 

NOTE 2: An INVITE dialogue also includes provisional responses (trying, your call is important to us) before the OK, but we will not concern ourselves with these for simplicity.

2:在OK之前,一个INVITE对话包含了预备的回应(trying, your call is important to us),但是简单起见,我们不涉及这些。

So, how is all this handled in ser.cfg? All SIP messages starting a new SIP transaction will enter the top of the main route{}. In the above, Johns INVITE starts a transaction that is answered with OK from Joan.那么,ser.cfg是如何控制所有这些呢?所有开始一个新SIP会话的SIP消息将进入main route{}的顶部。上面例子中,约翰的INVITE开始了一个会话,琼回答一个OK作为回答。

You have a lot of freedom in how SIP messages are handled in ser.cfg. For example, to record that Joan is online, you use the save(location) function for all REGISTER messages from Joans IP phone. A call to lookup(location) will retrieve where Joans IP phone can be found so that that a call can be made. Also, very limited info about Joans phone can be stored in the form of flags using the setflags() function. (From version 0.9.0 there is also support for attribute-value pairs that can be loaded/stored for a given subscriber, but more on this later).ser.cfg文件中,你拥有足够的自由度来控制这些SIP消息。例如,记录琼在线,你可以对所有REGISTER消息使用save(location)函数。调用lookup(location)函数可以找到琼的IP电话位置,便于进行呼叫。同样,使用setflags()函数可以存储非常有限的标志位信息(在版本0.9.0SER同样支持加载或存储指定用户的属性-值,只是新版本更多了(不知道but more on this later是不是这个意思)

The consequence of ser.cfg as a routing logic script is that you have to make sure that each SIP message type is handled correctly (flows through the script in a correct fashion) and that each possible response in a transaction is appropriately handled by reply or failure routes to realize what you want (forward on busy etc). This can be quite complex and opens up for many possible errors. Especially when changes to ser.cfg easily affect more than the messages you intended to target. This is usually the root cause of SER administrators that question whether SER is RFC3261 compliant or not. SER is RFC3261 compliant from point of view of can it properly process any particular SIP message, however any seemingly harmless error in ser.cfg can have dramatic impact on the SIP router and cause SER to deviate from RFC3261 compliance.作为路由逻辑脚本的ser.cfg的结果,取决于你正确的处理了每种SIP消息类型(脚本从头至尾按照正确的方式)以及处理过程中每个可能的反应都被reply或错误路由适当地按照你的意图处理了(如传送一个busy)。这可能会相当复杂并产生很多可能出现的错误,Especially when changes to ser.cfg easily affect more than the messages you intended to targetSER管理员产生疑问的根源通常在于SER是否遵守RFC3261SER遵守RFC3261,它可以处理所有SIP消息,但是ser.cfg文件中一些看起来无关紧要的错误却可能使SIP路由发生改变,从而令SER偏离RFC3261

This document presents a reference design with a corresponding ser.cfg to enable you to quickly set up SER to do what most people would like SER to do. 本文档给出了一些设计参考并附上相应的ser.cfg,以便用户可以很快的设置好SER来完成大多数用户想要SER来完成的工作。

Stateful vs. stateless 有状态vs无状态

An often misunderstood concept is stateful vs. stateless processing. The description of the INVITE SIP transaction above is an example of stateful processing. This means that SER will know that the OK belongs to the initial INVITE and you will be able to handle the OK in an onreply_route[x] block. With stateless processing (or simply forwarding), each message in the dialogue is handled with no context. Stateless forwarding is used for simple processing of SIP messages like load distribution.一个经常被误解的概念是statefulstateless处理。上面我们提到的关于INVITESIP处理是一个有状态处理。它的意思是SER将明白OK(消息)属于initial INVITE,你可以控制在onreply_route[x]模块中控制OK消息。在无状态处理过程中,对话中的每个消息的处理没有上下文依赖,无状态传递被用于简单的如加载分发SIP消息等简单的处理中。

In order to implement any advanced functionality like call accounting, forward on busy, voicemail, and other functionality in this documents reference setup, you will need to use stateful processing. Each SIP transaction will be kept in SERs memory so that any replies, failures, or retransmissions can be recognized. One consequence is that when using t_relay() for a SIP message, SER will recognize if a new INVITE message is a resend and will act accordingly. If stateless processing is used, the resent INVITE will just be forwarded as if it was the first.要实现高级功能如呼叫统计,忙时转接,语音邮件等,你需要使用有状态处理。每个SIP处理将存在于SER的内存中,任何回复、失败或者转播都可以被识别。一个可能的结果是,当对一个SIP消息使用t_relay()SER将辨识是否一个新的INVITE消息为重发信息并做相应处理。而如果使用了无状态处理,重发的INVITE将按新INVITE被简单的传递。

The confusion arises because this stateful processing is per SIP transaction, not per SIP dialog (or an actual phone call)! A phone call (SIP dialog) consists of several transactions, and SER does not keep information about transactions throughout a particular phone call. The consequence is that SER cannot terminate an on-going call (it doesnt know that the call is on-going), nor can SER calculate the length of an ended call (accounting). However, SER can store when an INVITE (or ACK) and a BYE message are received and record this info together with the Call-Id. A billing application can then match the INVITE with the BYE and calculate the length of the call. 有状态处理按照每SIP事物而不是每SIP对话(或真实的电话呼叫)进行,这样会导致混乱!一个电话呼叫(SIP对话)由很多事物组成,在一次电话呼叫中,SER不会保持这些信息。这样会导致的结果是,SER不能中断一个正在进行中的通话(它不知道这个呼叫已经在通话中),也不能计算通话时长。但是,SER可以保存一个INVITE(ACK)BYE消息收到的时间并按用户ID记录这些信息。一个帐单程序可以捕捉INVITE-BYE,并计算通话长度。

Understanding SIP and RTP 理解SIPRTP

In order to understand the subsequent sections, you must understand a few things about SIP and RTP. First of all, SIP is a signalling protocol handling the call control like inviting to a call, cancel (hang up while ringing), hanging up after ended call and so on. SIP messaging can be done directly from user agent to user agent, but often a SIP server is needed for one user agent to find another.为了理解后面的章节,你需要了解SIPRTP的一些概念。首先,SIP是信号化的协议用于呼叫控制,如邀请,取消,呼叫结束后挂起等。SIP消息可以直接从用户代理到用户代理传递,但是通常还是需要一个SIP服务器用于一个用户代理找到其它的代理。

When a SIP server like SER receives a message, it can decide that it wants to stay in the loop or not. If not, SER will provide the user agents with the information they need to contact each other and then SIP messages will go directly between the two user agents. SER这样的SIP服务器接受消息,它可以决定这个消息是否想待在此回路,如果不想,SER将提供两个UA彼此通信的信息,这样两个UA就可以直接通信啦。

If SER wants to stay in the loop, for example to make sure that a BYE message is received for accounting, SER must insert a Route header in the SIP message (using the record_route() function) to tell everybody that it wants to participate. In order for this to work, SER and potentially other SIP servers who participate must do what is called loose routing. A bit simplified, it means that SIP messages should not be sent directly to the user agent, but rather indirectly via all who have put a Route header in the SIP message (to check for such a recorded route, the loose_route() function is used).如果SER想保持在一个回路中,例如为了计时而需要确认BYE消息的接收。SER必须插入一个路由头到SIP消息(使用record_route()函数)告知所有人它想参与。为了这样工作,SER和其他SIP服务器必需要完成的是loose routing。简单地说,就是SIP消息不应该直接发送给UA,而需要间接通过所有添加到此SIP消息头的位置(检查这样有记录的路由,可以使用loose_route()函数)

SIP can also include additional information, for example related to how to set up a call with an audio or video stream (called SDP, Session Description Protocol). The SDP information will result in one or more RTP streams (or sessions) to be set up, normally directly between the two user agents. SER will NEVER participate in the RTP stream. RTP streams are by nature bandwidth and processing intensive. However, as we will describe later, SER can make sure that a third party application like a B2BUA or RTP Proxy can become the middle man.SIP可以添加附加的信息,例如如何设置一个拥有音频和视频流的呼叫(称为SDP Session Description Protocol)SDP信息将导致一个或多个RTP流被设置,(这些RTP)通常为两个直接连接的UA之间。SER不会参与到RTP流中。RTP streams are by nature bandwidth and processing intensive。后面我们将描述SER可以使用第三方程序如B2BUA或者RTP Proxy做中转。

Finally, the Real-Time Control Protocol (RTCP) communicates information about the RTP streams between the user agents (RTCP will either use the specified RTP port + 1 or the port indicated in the SDP message). 最后,实时控制协议(RTCP)完成两个UA之间RTP流的信息交流。(RTCP将使用RTP端口+1的端口号或者SDP消息指定的端口)。

Back-end applications and B2BUA 后台程序 B2BUA

We have learned that SER does not keep the state of a dialog, but just transfers SIP messages (as part of transactions) between two user agents. The consequence is that SER cannot be a peer in a dialog.我们前面提及过SER只在两个UA中传递SIP消息而不保存对话状态,这样导致SER 不能成为对话中的一方。(peer 是不是该这样翻译呢?)

But, if you want to play a voice prompt saying that the user is not available or provide voicemail capabilities, you will need something that can act as a user agent and be a peer in a SIP dialog, so that a session is actually set up between the calling user agent and that something playing the voice prompt. Modules or third party applications can provide this back-end user agent functionality, and SER will be in the middle. Again, SER is used in its stateful processing to enable these back-end applications.但是,当用户不在或者提供语音邮箱功能时播放一段语音提示,你需要一个可以在SIP对话中扮演另一UA的东西,这样一个会话将在呼叫者和播放语音提示的对象之间建立。模块或第三方程序可以提供这样的功能,SER将插入UA中间。此外,SER将用于有状态处理中来让这些后台程序开启。

NOTE: To add to the confusion, when SER is used in stateful processing to enable back-end user agent functionality, it is said to act as a stateful user agent server.

Also, if you want to implement a pre-paid service, you have a problem because SER cannot terminate the call when no money is left! In this scenario you need a third party in the SIP dialog (and quite possibly in the session). This third party will act as the middle man both in the SIP messages and in the audio. Thus, each user agent will only talk to the middle man and not know about the remote user agent. This middle man is what you probably have seen referenced as a B2BUA (Back-to-Back User Agent) on the ser users mailing list. A B2BUA can handle SIP messaging only or both SIP and RTP. 另外,如果你想要实现先付款服务,你将面对一个问题因为当没有余额时SER并不能中止呼叫!这时,你需要在SIP对话(应该是会议中)中加入第三方。第三方将在SIP消息和语音流中扮演中间人角色。这样,每个UA将只能和中间人通话而不需要了解另一方UA。你可能在SER用户邮件列表中看到过的这个中间人,B2BUABack-to-Back UA)。

NAT, STUN, and RTP proxy

One of the things causing the most problems is one-way audio or no audio when dealing with user agents behind NAT devices that attempt to communicate with user agents on the public internet or behind a different NAT device. These NAT devices can be ADSL routers, firewalls, wireless LAN routers, etc. In order to understand NAT and RTP proxying, you must understand what happens when a user agent registers with a SIP Registrar and when a call is made.NAT设备之后尝试与公网或其它NAT设备之后的UA进行通话通常会导致的问题是只有单方语音或没有声音。这些NAT设备可能是ADSL路由器,防火墙,无限局域网路由器等等。为了了解NAT以及RTP代理,你需要理解当UA使用SIP注册以及呼叫时都发生了什么。

In the following sections, functions from the nathelper module will be used as examples. Mediaproxy will be covered later in this document.下面的章节将使用nathelper模块的函数作为例子,Mediaproxy将在文档后面提及。

NOTE: SER has two different offerings for dealing with NAT and RTP proxying, namely rtpproxy and mediaproxy. These two solutions work independently of each other and are covered else where in this document. Much confusion has been caused by these two NAT solutions. Also, the nathelper module noted above is generally considered part of the rtpproxy solution, although you can use its exposed functions with mediaproxy. 注:SER提供两个不同的用于处理NATRTP代理的东西,它们是rtpproxymediaproxy。这两个方案各自独立工作并都将在此文档中被提及。这两个NAT解决方案将带来更多的混乱。同样,nat helper模块考虑到上诉问题一般使用rtpproxy方案的端口,尽管你也可以使用它提供的mediaproxy函数。

Registration behind NAT  NAT后面的注册

When a user agent contacts SER with a REGISTER message, the user agent will only see its private IP address behind the NAT (ex. 192.0.2.13). Thus, it will believe that the correct contact information is myself@192.0.2.13:5060 and will include that in the REGISTER message (port 5060 is assumed to be the port the user agent is listening on). Of course, nobody can reach myself@192.0.2.13:5060 on the Internet as this address is valid only behind the users NAT device.UA使用REGISTER消息联系SERUA只能看到NAT后面的私有IP(如192.0.2.13)。这就是说,它将认为正确的连接信息为myself@192.0.2.13:5060 并把它写入REGISTER消息中。(假定UA监听的端口为5060)。当然,在Internet上没有人能连接到myself@192.0.2.13:5060因为这个地址只在NAT内部有效。

SER will receive a REGISTER message from a.b.c.d:f where a.b.c.d is the public IP address of the NAT and f is the to port allocated by the NAT to this communication just initiated. SER will be able to respond to a.b.c.d:f and reach the user agent and must therefore register this address instead of the one presented by the user agent. Nathelpers function for testing if the user agent is behind NAT is called nat_uac_test(). A parameter can be specified to indicate which tests should be done. We recommend using 19 (all tests). A description of the various tests is beyond the scope of this document.SER将接收REGISTER消息来自a.b.c.d:fa.b.c.dNAT的公网IP地址,f为连接发起时NAT分派的端口。SER将可以回应a.b.c.d:f ,连接到UA,记录这个地址来替代UA当前的地址(UANAT内部地址)Nathelpers 用于测试UA是否在NAT后面的函数为nat_uac_test()。可以指定一个参数用于需要完成什么样的测试。我们推荐使用19(所有测试)。关于各种测试的描述超出了本文的范围。

Also, SER must record whether the user agent is behind NAT in order to properly process later messages. This is done by setting a flag for the UA using the setflag() function. This flag will be available for testing for both caller and callee.另外,SER必须记录UA是否在NAT之后,以便于恰当的处理后面的消息。使用setflag()函数设置一个标志来完成这件事情。

Nathelper provides the fix_nated_contact() function for re-writing the Contact header. This action is not strictly according to the RFC, so nathelper (>0.9.0) has another function fix_nated_register() that will only register the correct address and port without rewriting the Contact header. Nathelper 提供了fix_nated_contact()函数用于重写联系头。这个函数的行为没有遵守RFC,在nathelper0.9.0版本后)提供了另外一个函数fix_nated_register(),它将只注册联系地址和端口并不重写联系头。

NOTE: Section 10.3 of RFC3261 says you must not alter the contact header while processing REGISTER messages, therefore, you should never use fix_nated_contact() while processing REGISTER requests. Instead, always use fix_nated_register() and use fix_nated_contact() for all other message types. 注:RFC326110.3章中这样说,处理REGISTER消息时,你不能修改contact header,因此,在处理REGISTER请求的时候最好不要使用fix_nated_contact()函数,而使用fix_nated_register()来代替。处理其它消息时,使用fix_nated_contact()

Also, the core function force_rport() is often used for all NATed messages to ensure that the Via headers (used for matching transactions etc) include the remote port number. This way the response in the transaction is sent back to the correct port. This only works for clients that support symmetric signalling (listen on the same port as they send). However, most clients are now symmetric.同样,核心函数force_rport()也会经常用于NAT间的消息。它确保经由的headers包含远程端口。这样事务处理中的回应可以回传到正确的端口。它只能用于支持symmetric signalling(发送监听同一端口)的客户端,还好大多数客户端都是symmetric

An extra problem is that the NAT device will only reserve port f for a certain time, so if nothing more happens, the NAT will close the port and ser will not be able to contact the user agent. This is solved by either the user agent sending regular messages to SER or SER must send regular messages to a.b.c.d:f (keep-alive).另外的问题是NAT设备只在特定的时间存储f端口,这样要是没有发生其它的事情,NAT将关闭这个端口,这样SER将不能连接到UA。解决方法是UA或者SER定时发送消息来保证a.b.c.d:f是活动的。

INVITEs behind NAT NAT后面的邀请

When an INVITE message is sent from a user agent, it will contain an SDP (Session Description Protocol) payload (read attachment or content). This payload describes various things about the user agent, ex. what type of sessions it supports, and where the party being called can reach the caller. As above, this information will for example be 192.0.2.13:23767. 23767 is the port the user agent has allocated and where it will listen for the actual sound (Real Time Protocol/RTP) for the session. At the time of the INVITE, there is no corresponding port on the NAT (as no RTP has yet been sent). The related SDP lines in the INVITE would look like this (c=contact, m=media):当一个INVITE消息来自UA,它将包含一个SDP负载,这个负载描述了关于UA的很多信息。例如 它支持什么类型的会话,哪里的被叫用户能连接到等。同上,以192.0.2.13:23767为例表示这些信息。23767为分配给UA的端口,它将在这里监听会议的音频(RTP)。在INVITE的时候,NAT还没有相应的端口(还没有RTP的传输)。所描述的INVITE中的SDP列看上去应该像这样,(c=contact, m=media):

c=IN IP4 192.0.2.13.

m=audio 23767 RTP/AVP 0 101.

In addition, the contact information will, as for the REGISTER message, be wrong. SER must change the contact information to the public address a.b.c.d:f as for the REGISTER message. With nathelper, this is done by calling fix_nated_contact(). Other transaction-starting messages like ACK, CANCEL, and BYE should also have the contact header fixed.同样,和REGISTER消息一样,这个连接信息是错误的,SER必须改变此信息为类似于REGISTER消息的公网地址a.b.c.d:fnathelper中,调用fix_nated_contact()函数来完成此工作。其它事务-开始消息如ACKCANCELBYE都需要对联系头做修正。

For the audio, SER can only do three things with the INVITE before forwarding to the user agent being called:对于音频,SER在发送INVITE到用户前,只能做三件事:

1.      Add an SDP command direction:active to the SDP content 添加SDP命令:作用于SDP内容

2.      Change the c= line to a.b.c.d 改变“c=”行为a.b.c.d

3.      Force RTP to go through a proxy by changing the c-line to c=IN IP4 address-of-proxy and the m-line to m=audio port-on-proxy RTP/AVP 0 101.修改c-linec=IN IP4 address-of-proxy m-linem=audio port-on-proxy RTP/AVP 0 101. 来强制RTP通过代理传递。

#1 is a way to tell the called user agent that it should wait until it receives audio and then just assume that it should send its own audio back to the same address (this is called symmetric RTP). This only works for user agents with a public IP or with a known RTP port on the NAT (for example by using STUN). If both are behind NAT, both will wait for the other to start and nothing will happen. However, this can be a good method for PSTN gateways with public addresses. You do this with nathelper by calling fix_nated_sdp("1").  #1 是告诉UA它需要等待直道接收到音频然后假定它应该发送它自己的音频回相同的地址(称为对称RTP)。它只在UA为公网IP时或者已经知道NATRTP端口时工作。如果两个UA都在NAT后面,两者都在等待,什么都不会发生。然而,对于拥有公网IPPSTN,它仍旧是一个很好的办法。使用nathelperfix_nated_sdp("1").函数来完成此工作。

#2 is basically the same as #1, but the called user agent gets some more information. You can do this with nathelper by calling fix_nated_sdp("2"). You can do both #1 and #2 at the same time by specifying 3. #2 #1很相似,但是被叫UA得到了更多的信息。你可以使用nathelperfix_nated_sdp("2").函数完成此工作。

#3 means that you need to set up a separate daemon called an RTP proxy (with a public IP address) that both user agents can send their audio to. You thus add an extra step (which can add latency in the audio) and for each call you need to handle 2 x required bandwidth for the codec the user agents are using (ex. 88 Kbps for G.711). With nathelper, you call force_rtp_proxy(). #3意味着你需要单独设置一个叫做RTP代理的后台程序(拥有公网IP),所有的UA都发送语音到RTP代理。这个你需要额外的步骤,每个呼叫都需要2倍的带宽用于UA使用的编码解码器(如88 Kbps for G.711)。你可以使用force_rtp_proxy().来完成此工作。

Please note that the calling user agent can have a public IP address, while the called user agent is behind a NAT. The OK returned by the called user agent will have to be manipulated as above and thus NAT handling code must also be included in the onreply_route[x] part of ser.cfg. The called user agent also has the flag set as described in the REGISTER section above (setflag). So, in the onreply route one can check whether the called user agent is behind NAT. If so, the contact header should be changed and (if desired) RTP proxying enforced. 请注意,胡椒UA可能拥有一个公网IP,此时被叫用户在NAT之后。被叫UA返回的OK将必须按照上面所说进行操作,这样NAT控制代码必须包含进 ser.cfgonreply_route[x]部分。被叫UA也拥有一个标志位(就象前面的REGISTER部分)。这样,回复路有可以被叫用户是否在NAT之后,如果是的话,联系信息将被修改,并强迫使用RTP代理。

STUN

Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs) also known as STUN… 简单UDP穿透NAT也被叫做STUN

STUN is a protocol for the user agent to discover its own public IP address. You will need to install a STUN server (not part of SER). The user agent will then try to change the contact and SDP information itself. When STUN is used by a user agent, SER does not have to do any rewriting as described in previous section. The exception is when a user agent is behind a symmetric NAT (the different types of NAT is beyond the scope of this document). In this situation the user agent should NOT try to rewrite as the STUN protocol will provide the wrong port. SER can then be used to rewrite contact and SDP information for these situations. For outgoing calls from a symmetric NAT, the direction:active rewrite can be used, but calls between user agents behind symmetric NATs must always be handled with an RTP Proxy server.   STUN是一个用于UA发现它自己公网IP地址的协议。你需要安装STUN服务器(这不是SER的一部分)。UA将尝试改变自己的contact以及SDP信息。当UA使用了STUNSER不需要像上面章节描述的那样修改任何东西。当然一个对称NAT后面的UA除外(各种类型的NAT的讨论超出本文范围),在这种情况下,UA不应该去重写,因为STUN将提供一个错误的端口。此时,SER将会重写contact以及SDP信息。对于UA在对称NAT内的对外呼叫,地址动态重写将被使用,但是在对称NAT之间的UA必须被RTP 代理服务器控制。

WARNING: Some user agents have faulty implementations of STUN. If STUN then has a wrong conclusion, you may end up with one-way audio (or no audio) or calls that are disconnected. Some situations can actually be detected by SERs NAT detection tests (by comparing the senders source address/port with the contact header in the INVITE, nathelper test flag 16), but it is recommended to test new user agents in different NAT scenarios to make sure that a combined. 警告:某些UA并没有完全实现(对)STUN(的支持)。如果STUN得到错误的结果,将会出现单线语音(或无语音)或者不能连接的结果。事实上,一些解决方案可以通过SER来检测NAT(使用nathelper测试函数(可能是nat_uac_test()吧)标志位16来比较在INVITE消息中contact的源地址、端口号),但是它被推荐用于测试在不同NAT间的新UA scenarios to make sure that a combined.(介怎么翻啊~…

Other non-ser NAT traversal techniques 其它非serNAT穿透技术

Some NATs and firewalls have a built-in SIP Traversal mechanism, such as Cisco 3600 routers with IOS version 12.3(9). Such a capability is often referred to as an Application Level Gateway (ALG). A SIP ALG will rewrite all SIP messages transparently (both ways). If this is done correctly, both the user agent and SER will be happy. If not, nobody is happy and you either have to turn off the ALG in the router or you have to use SER on another SIP port (like 5065). However, you will then get other NAT-related problems. The fix-faulty-ALG-problem is not really possible to do in SER 0.9.0, but the next version will introduce new features designed to address this issue. 某些NATs 和防火墙拥有内置的SIP穿越机制,例如带有12.39)版本IOSCisco3600路由器。这样的功能被称为应用级网关(ALG),一个SIP ALG 会重写所有的SIP消息,如果它正确的工作,UASER都将很好的工作,如果它没有正确的工作,UASER都不能很好工作,这时你需要关闭路由器上的ALG功能,或者你需要SER使用另外的SIP端口(如5065)。即使这样,你可能还会遇到有关NAT的问题。SER0.9.0中并不需要解决ALG问题,但是后面的版本将引入新的功能来从事这些事情。

A second variant is Session Border Controllers (SBC). These are difficult to define as a group as they can do many things, but most often they will act as a full B2BUA (terminate the SIP and RTP sessions for both user agents so that both only see the SBC). SBCs are most often used by service providers to control the edge of their networks. 另一种技术叫做 会话边界控制(SBC)。很难为SBC定义它可以完成什么功能,但是它经常会扮演B2BUA角色(终止UA间的SIPRTP会话,它们只能看到SBC)。SBCs经常用于提供网络边界控制的服务

URI, R-URI, and Branches

The URI, Uniform Resource Identifier, is used to identify a user uniquely. The URI is used as an address when INVITEing a party to a call. A typical SIP URI is in the form sip:username@domain.com. The original URI found in the first line of a SIP message is called the request-URI (R-URI). This uri can be referred to in ser.cfg using uri (ex. if(uri=~sip:username@.*) ) 通用资源标志符,简称URI。它用于唯一地识别用户。当INVITE一个呼叫时 URI作为一个地址。典型的SIP URI格式如下 sip:username@domain.com 。最初的URI位于SIP消息的第一行,被称为请求URIR-URI)。这个URI可以在ser.cfg中使用uri得到(例如:if(uri=~sip:username@.*)

The uri can be manipulated throughout ser.cfg using many different functions from different modules. For example, lookup(location) will take the uri as changed through uri manipulations, look it up in the location database and rewrite the uri to the correct contact information (including @ipaddress:port). When t_relay() is called, the URI in it final form after transformations will be used as the target URI.  uri 在整个ser.cfg中可以被多个模块所使用。例如lookup(location) take the uri as changed through uri manipulations,察看本地数据库重写uri为正确的contact信息。(包括 @ ipaddress:port) .t_relay()调用后,它里面的修改过的URI将成为目标URI

Some functions, like lookup(location) can append branches to the target set of URIs. This means that when t_relay() is called, the INVITE message will be duplicated to all the URIs in the target set. Note that the uri command will still refer to the request-URI in its (potentially) transformed form. The core command revert_uri() will replace the current target URI back to the original request-URI. 某些函数如lookup(location)可以在目标(target setURI中添加分支。这就是说,当t_relay()调用后,INVIVTE消息将复制所有的URI到目标(target set)。注意,这个uri命令将仍旧将R-URI 转换为自己的格式。内核 命令revert_uri() 会还原当前的目标URI为最初的R-URI

NOTE: A backported version of xlog (to 0.9.x) has new parameters that can be used to print the full target set. The backported version can be found on http://www.onsip.org/ 注:backported版本的xlog拥有新的参数可以用于打印所有的target set。可以从http://www.onsip.org/找到此版本。

posted on 2007-10-22 19:30  Alex Lee  阅读(5009)  评论(0编辑  收藏  举报