首页 >> 欧式家具

最火完整SIPSDP媒体协商概论2休闲皮鞋卫星模型女士浴衣华为手机爆谷机We

时间:2023/02/15 20:41:28 编辑:

完整SIP/SDP媒体协商概论

在前面的章节中,我们主要讨论了ICE概览,介绍了ICE的基本处理流程和候选地址配对的算法概论和轻量级ICE部署(Lite Implementations)的讨论。和前面介绍中讨论的SIP中offer的处理一样,在此文章中,笔者也将首先介绍ICE处理过程中初始offer的发送处理。因为轻量级的ICE部署场景不是RFC5245推荐的场景,本身协商也忽略了很多检查流程,所以笔者还是按照规范的的重点内容来讨论全部署场景(Full Implementations)中关于初始offer的处理,结尾部分将讨论轻量级ICE部署的场景和SDP解码。

1全部署场景处理要求

在全部署场景中(Full Implementations),初始offer的处理大概需要经过五个主要的步骤:候选地址获取- 候选地址优先级处理- 移除冗余候选地址- 选择默认候选地址,最后计算发送SDP offer。下面,笔者将会一步步介绍其中最主要的前四个步骤。

首先,笔者介绍一下候选地址获取或者采集(Gathering Candidates)。在日常生活环境中,如果我们计划出去旅游的话,我们一般都会提前准备旅游线路的一些背景资料,例如交通信息,旅游资料方便我们找到最佳的旅游路线,在最低成本的前提下获得最佳运动地板的旅游体验。同样,候选地址获取也是一样的。当agent之间的通信即将开始时,agent需要获取候选地址。agent或者offer提供方可以通过操作界面的提示或外部的初始请求来发起一个offer消息。每个候选地址就是一个传输地址,它也包括其类型和base。候选地址8.送油阀稳压弹簧刚度低或节流针空腔有梗塞的base实际上也是一种候选地址(一个基准地址),当agent使用候选地址时,agent必须从此地址发送。在RFC5245中,规范定义了四种候选地址类型,它们分别是host candidates,server reflexive candidates,peer reflexive candidates和relayed candidates。其中,server reflexive candidates是通过STUN或者TURN服务器获得,relayed candidates是通过TURN服务器获得,peer reflexive candidates则是通过ICE协商过程中获得(它事实上是一种连接性检查的结果,不做讨论)。关于以上四种类型的定义,笔者在前面很多历史文章中结合一些图例有一些介绍,这里为了能够更好配合SDP的介绍,保持关于SDP内容讨论的完整性,笔者再花费一点时间重新梳理一次前三种候选地址类型。

Host candidates(主机候选地址)是首先需要获取的地址。主机地址是通过端口和IP地址绑定获得。这里的IP地址可以此主机所属的物理口IP地址,虚拟地址或者VPN地址。agent想调用UDP媒体流的话(也可以通过拓展支持TCP),agent应该获得本地主机支持的一个候选地址,这个候选地址是针对每个媒体流构件的,这些媒体流通过主机所支持的IP地址来传输。agent通过绑定一个具体的IP地址和端口来获得每个候选地址。每个媒体构件有一个component ID,基于RTP的媒体流,它本身就有一个ID,这个ID是1,RTCP的ID是2。如果agent使用了RTCP的话,它必须获取一个候选地址;如果agent使用RTP和RTCP的话,agent有k个IP地址的话,它必须以2*K的主机候选地址来最终地址计算方式。针对每个主机候选地址来说,base基准地址是候选地址自己本身。

Agent除了需要获得主机候选地址以外,agent应该获得Server Reflexive (反射地址)和 Relayed Candidates(转发地址)两种候选地址。读者注意,这里使用的是应该而不是需要或者必须,使用的要求取决于提供者的环境变量要求。在有一些使用场景中,Server Reflexive 和 Relayed Candidates都是和公绑定的,因此agent在一个封闭络环境中,或者从来不连接公的话,没有必要使用Server Reflexive 和 Relayed Candidates地址。如果agent支持了双络协议或者支持多宿主地址的话,agent应该使用全部署方式来处理候选地址。部署TURN服务器的成本是非常高的,需要考虑实际场景。当使用ICE时,agent双方都在NAT后,它们需要一个地址和端口映射处理时,用户才需要考虑使用NAT部署。在后续部署使用过程中,可能一些用户会把使用NAT地址映射作为一种用户场景来满足agent的支持能力,因此,通常这种可选的边缘处理的用户场景仅作为一种可选方案,可能也不会经常使用。因此,如果agent不采集Server Reflexive(反射地址) 和 Relayed Candidates(转发地址)的话,RFC5245规范推荐关闭这种部署文件配置。如果将来络环境发生了变化,agent可以通过配置开启采集地址的功能。这里再次重复一次笔者前面提到的废话。如果agent正在采集Server Reflexive(反射地址)和 Relayed Candidates(转发地址)的话,agent需要使用TURN服务器。如果agent仅采集反射地址的话,agent使用STUN服务器。部署场景决定以后,agent开始其候选配对的处理流程,agent可以通过界面配置方式或者其他的侦测手段(通常是通过GUI界面配置STUN/TURN服务器地址),通过STUN或者TURN服务器对其每个主机候选地址进行配对。如果已配置好了STUN或者TURN服务器的话,规范推荐配置一个domain名称,使用DNS处理流程来发现STUN服务器和TURN服务器地址。

这里的DNS处理流程遵从两个规范(RFC5389和RFC5766),分别实现对STURN服务器的查询和TURN服务器的查询。其中,查询STUN服务器地址的流程是通过Service Records (SRV),使用 stun 服务来完成的,具体的流程按照RFC 5389的DNS流程实现。查询TURN服务器地址的流程是通过SRV,使用 turn 服务来完成,具体的流程是按照RFC5766规范DNS流程实现。在具体的应用场景中,agent可能会通过学习从SRV查询中获得多个STUN或者TURN地址。根据RFC5245规范的说明,为了提升ICE的处理性能,在一个具体的会话中,对于所有候选地址来说,agent应该仅使用单个STUN或者TURN地址。查询的结果就是通过STUN或TURN服务器的一系列主机候选配对。agent然后从一系列配对中选择一个配对,从主机候选地址对STUN或者TRUN服务器端发送绑定或分配请求。特别注意,对STUN服务器来说,发送绑定请求是不需要签权的,响应中任何服务器属性(ALTERNATESERVER)都会被忽略掉,同时agent必须支持向后兼容的模式支持绑定请求(Binding request),此绑定请求在RFC5389中说明。分配请求(Allocate requests)应该需要通过签权认证流程,agent端可以设定一定的安全机制来实现签权流程。

在ICE采集候选地址阶段,ICE设置了一个定时器(Ta),每Ta毫秒后,agent就会生成一个新的STUN或TURN事务。这个事务可以是针对前一个事务的重试,在这个新事务中可以携带一定的错误消息(例如,认证错误)。这个事务也可以是一个新的事务,新的事务可支持新的主机候选配对和STUN/TURN服务器配对。为了保证其ICE采集流程的稳定性,不影响其他定时器的使用(例如,STUN重传定时器RTO的),agent不应该在每Ta毫秒内过于频繁生成新的事务。关于这两种定时器的使用方式,我们在后续章节会涉及,这里不再深入讨论。发送了绑定请求或分配请求后,agent将会收到一个绑定或分配请求的响应消息。如果收到的是一个成功的分配响应消息的话,消息中会包含Server Reflexive地址(反射地址,从映射地址中获得) 和 Relayed Candidates(转发地址)。其中,转发候选地址是在响应消息的XOR-RELAYED-ADDRESS属性设置中。如果分配请求被拒绝的话,那是因为服务器端没有可提供的资源来支持这个请求,agent应该对服务器端发送一个绑定请求来获得反射候选地址,绑定请求将会对agent提供一个反射候选地址(也是从映射地址中获得)。反射候选地址的基准地址是一个主机候选地址,这个主机候选地址是发送绑定请求和分配请求的地址。转发候选地址的基准地址是候选地址本身。对主机候选地址来说,如果转发候选地址是确认状态(很少发生的极端情况),那么,这个转发候选地址必须要丢弃。

除了采集反射候选地址和转发候选地址以外,最后,agent还要对每个候选地址分配一个foundation。Foundation是一个身份标识符,它在会话中使用。Foundation ID 用来决定两个候选地址是否相同。计算foundation目前没有特定的说法,它仅针对配对的计算,保持其唯一性。如果要保证两个候选地址具有相同foundation ID的话,以下四个条件需要都为真:

候选地址具有同样的类型(主机候选地址,转发候选地址,反射候选地址或者peer 反射地址)

它们的基准地址具有同样的IP地址(端口可以不同)

对反射候选地址和转发候选地址来说,通过STUN或者TRUN服务器获得这些地址,这些地址必须具有同样的IP地址

通过同样的传输协议(TCP/UDP,或者其他)获得候选地址

反之亦然,如果以上其中一个条件不为真的话,则说明候选地址具有不同的foundation。

采集到反射候选地址和转发地址以后,为了保证ICE的正常工作,这种绑定关系需要一定的维护机制来保证此地址的连接性。因此,反射地址和转发地址一旦分配以后,这些地址必须保持一个存活状态。在后续章节中,笔者将继续介绍关于释放候选地址话题。对于通过绑定请求学习到的反射候选地址来说,这种绑定关系必须通过对服务器端发送其他的额外请求才能继续维持。分配请求可以通过刷新事务的方式来实现,具体的处理方式,读者可以参考RFC章节。刷新请求也同样刷新了反射候选地址。

到此为止,笔者讨论了采集候选地址所关注的几个主要话题(主机候选地址,反射地址,转发地址,foundation计算和候选地址的状态维护)。接下来,笔者将继续讨论关于针对候选地址优先级排序以及其计算方式和指导原则。

为了保证ICE的传输取得最佳的性能,候选地址需要进行优先级的处理。优先级处理针对每个候选地址指定了一个优先级标识。传输媒体流的每个候选地址必须有一个唯一的优先级,此优先级必须是一个正数,取值范围在1到(2**31 - 1)之间。ICE将使用此优先级取值来决定检查连接性的依据,和对候选地址进行修改偏好的选择参数。Agent将使用计算公式来计算其优先级,计算公式所使用的参数根据规范的指导原则进行。如果agent使用不同的计算公式的话,双方agent对连接性检查流程可能出现不协调的情况,因此,ICE将会耗费更长的时间汇聚数据交互。下面,笔者将针对计算公式和具体的指导原则进行说明。

候选地址具有两支承辊优先级计算

通过以上公式可以看出,使用格式计算优先级时,永久性的结果计算关联了三个主要的参数(针对每个候选地址类型的偏好,本地IP地址和component ID)。其中,每个候选地址类型的偏好取决于候选地址的类型(host candidates,server reflexive candidates,peer reflexive candidates和relayed candidates)。如果agent是一台多宿主的主机,其偏好取决于主机的IP地址。类型偏好(type preference)必须是整数,取值范围从0到126范围内,表示四种候选地址的偏好。126是最高偏好取值,0是最低偏好取值。如果对候选地址类型的偏好设置为0,则表示这个类型的候选地址将为最后的一种选择。同样类型偏好的候选地址必须要确认其相同性,不同的类型偏好的也需要确认其不同。以上四种候选地址类型的优先级也具有不同的判断级别。其中,peer reflexive candidates的类型偏好优先级必须高于其他反射候选地址类型偏好。本地偏好(local preference)必须是整数,取值范围从0到65535范围内。它表示的偏好是针对具体的IP地址的,从这个具体的IP地址获得候选地址,agent是一台多宿主主机。65535是最高偏好取值,0是最低偏好取值。当切管机本地主机只有单个IP地址时,偏好取值应该设置为65535。通常情况下,如果针对一个具体的媒体流的特别构件支持了多个候选地址的话,此特别构件的多个候选地址具有相同的类型的话,针对每个候选地址的本地偏好必须是唯一的。在RFC 5245规范中,以上这种情况仅发生在多宿主主机环境中。因为多宿主主机是一个双栈主机,本地偏好应该等同于IP地址的优先值。关于优先值的取值读者可以参考RFC.1,因为现在很多场景中已经部署了IPv6,,因此,可能在某些场景中,IPv6的优先级高于IPv4的优先级。具体的优先值计算取决于具体的场景中。component ID是候选地址的component ID,它的取值范围必须在1到256之间。介绍完计算公式以后,笔者接下来需要讨论选择类型偏好和本地偏好的四个指导原则或标准。

第一个指导原则是选择类型偏好和本地偏好需要根据一定的标准。类型偏好和本地偏好取值是主要标准,具体来说,就是媒体的中间介质的使用,例如TURN服务器,VPN或者NAT。在使用这些媒体中间介质时,如果媒体发送到这些介质的候选地址,在收到媒体之前,媒体需要首先被发送到中间介质的候选地址。转发候选地址就是其中一种候选地址类型,它涉及了媒体中间介质。另外一种媒体中间介质就是通过VPN接口获得的主机候选地址。显然,当媒体通过媒体中间介质以后,它会增加发送和接收方之间的时延。同时,因为媒体经过了多个路由器hops,增加了丢包的风险。当然,因为媒体需要进出媒体中间介质的服务器,服务提供商也需要相应增加部署成本。如果用户觉得笔者前面说的这些因素是非常重要的,因为考虑到这些风险的重要性,转发候选地址的偏好设置就应该要低于本地偏好设置。因此,针对偏好取值的取值可能需要做一定的调整。推荐的办法是,本地候选地址偏好设置为126,反射候选地址偏好设置为100,peer reflexive candidates设置为110,转发候选地址的偏好设置为0。进一步说,如果agent是一台多宿主主机,它本身带多个IP地址的话,从VPN接口获得的主机候选地址的本地偏好设置为0。

来自于互联资源

选择偏好的第二个指导原则是基于IP组选择方式。ICE可以在IPv4和IPv6络环境中工作。ICE提供了一种工作机制,可以保证双栈主机选择IPv6,但是万一IPv6络出现故障时(例如,在6to4路由器转发失败-RFC3056),它也允许主机回退到IPv4的络环境中。ICE也可以帮助主机获得原生的IPv6地址和6to4地址。如果是我们以上所说的这种情况的话,相对比较高的本地偏好将会关联到IPv6的地址,然后是6to4的地址,最后才是IPv4的地址。这样安排的目的是允许agent可以马上优先使用原生IPv6地址,如果出现连接问题或者对端agent没有启用原生IPv6时,可以退回到6to4的地址继续和对端通信。

第二个原则选择偏好的原则是基于主机IP地址的类型。第三个原则是基本上是基于第二个原则的基础上,针对络最重要的问题(安全机制)的选择。因此,根据安全机制选择偏好也是一种非常重要的指导原则。现在国际上很多公司的员工都是远程办公(特别是WebRTC终端方式),如果远程办公员工提供家庭私人络访问企业内部络时,员工端希望通过企业内部络访问语音流量,通过企业通信系统呼出到其他外部目的地。这样的话,员工私人络和企业络之间就需要一个VPN的连接或者SBC的连接(笔者已经介绍过很多关于SBC的使用,这里仅指VPN)。如果是这样的部署场景的话,和其他后续地址相比,VPN地址将具有比较高的本地偏好优先级。

第四个选择偏好的指导原则是关于络拓扑意识。企业络的拓扑设计也是选择偏好时需要关注的地方。候选地址的处理如果可以灵活地充分利用络优势也可以优化地址的选择。对于后续地址来说,它可以利用其中间介质的多种已存络架构实现偏好选择。在某些络环境中,如果agent可以预设或者动态发现中间介质,这些中间代理介质可能是最佳(或最近)的路径地址包括候选地址的话,agent应该设定此候选地址的本地偏好为比较高的优先级。

前面,笔者介绍了候选地址采集和候选地址的优先级处理。接下来,我们继续介绍优先级处理以后的另外一个话题,这就是关于候选地址冗余移除的问题。为了保证agent端本身存储和管理的问题,agent会移除一些冗余的候选地址。如何判断候选地址是重复或是一个冗余地址呢?根据RFC5245的说明,如果一个候选地址的传输地址等于其他候选地址的传输地址,并且此候选地址的基准地址等于其他候选地址的基准地址,那么此候选地址就是一个冗余候选地址。另外,如果候选地址的传输地址相同,但是它们的基准地址不同,这些候选地址不是冗余候选地址。很多情况下,当agent没有在NAT背后时,反射候选地址和主机候选地址是冗余或者重复的,agent应该设置一个比较低的偏好优先级移除这些冗余候选地址。

采集到候选地址以后,接下来就需要考虑如何设置一个默认的候选地址实现媒体流的进一步传输处理。如果一个候选地址被看作是一个默认的候选地址的话,从非-ICE用户端来说,它将作为一个媒体目标。这个媒体目标称之为DEFAULT DESTINATION(默认目的地)。如果当agent和一个ICE-aware peer(能够感知到ICE的远端)通信时,如果ICE算法没有选择候选地址的话,ICE处理流程完成以后,agent要求一个updated offer/answer 来修复或者纠正SDP,这样的话,媒体默认的目的地地址将会匹配ICE已选的候选地址。当然,如果ICE选择了默认的候选地址,agent就没有必要发送更新的offer/answer。

Agent 必须选择一组候选地址,每个在使用的媒体流的每个构件的一个候选地址作为默认的候选地址。如果端口不是0的话,说明媒体流正在使用其构件端口。这个结论我们在前面的讨论中已经说明。接下来处理中,尽管a=inactive状态或者bandwidth设置为0,媒体仍然会置于使用状态。

RFC5245规范推荐选择默认的候选地址是基于候选地址的概率,具体来说,这些候选地址和对端peer已经关联在一起的概率,或者它们之间的一起工作的概率来决定。规范推荐的默认候选地址是,转发候选地址(如果有转发地址的话),反射候选地址(如果有反射候选地址的话)和最后主机候选地址。

2轻量级部署要求

前面所讨论的都是基于全部署场景的内容。轻量级部署(Lite Implementation)相对比较简单,它仅使用了主机候选地址。轻量级部署必须为每个媒体流的每个构件分配0个或者一个IPv4的地址。轻量级部署它可能分配0个或者一个IPv6地址,但是,主机不能使用多余1个以上的IPv6地址。因为很多时候,每个媒体流的每个构件可以支持多个IPv4候选地址,如果agent支持多个IPv4地址的话,它必须从分配的候选地址中选择其中一个地址。如果主机支持的双栈地址的话,RFC5245推荐分配一个IPv4候选地址和一个全局IPv6地址。在轻量级的部署场景中,ICE不能用来动态选择一定范围内的候选地址。在完整的ICE流程中,通过连接性检查才能真正决定使用这个地址或者那个地址。因此,规范也不推荐从一个特定的络区域内包含一个以上的候选地址。

每个构件/模块都会设定一个ID,我们称之为component ID或者模块ID。对于RTP媒体流来说,RTP自己的ID为1,RTCP为2。如果agent正在使用RTCP的话,它必须首先获得一个候选地址。

每个候选地址会设定一个foundation。两个从不同IP地址获得的两个候选地址,这两个候选地址的foundation肯定是不同的,如果从相同的IP地址获得的候选地址的话,foundation看到是相同的。这里的foundation计算方式和全部署场景的要求有所不同(同时也要求检查端口)。对于优先级的计算公式来说,对每个IP地址来说仅依靠一个简单的整数递增是不够的。另外,针对同样的媒体流,在所有候选地址中,每个候选地址必须设定一个唯一的优先级标识。优先级的计算公式如下:

轻量级部署场景中优先级计算公式

在以上格式中,如果主机仅有IPv4地址的话,IP precedence设置为65535。如果主机是IPv6地址或者是双栈地址的话,IP precedence应该是RFC3484中的precedence值。

接下来,agent将会为每个媒体流的每个构件选择一个默认的候选地址。如果主机地址仅支持IPv食品模具4地址,主机将仅对每个媒体流的每个构件选择一个候选地址,因此,这个候选地址是默认地址。如果主机支持支持IPv6或者双栈地址,默认地址的选择取决于本地策略。默认候选地址的可能是一个经常用来和对端peer通信的候选地址(参考前面章节的第四种指导原则)。简单来说,默认候选地址更多倾向于使用以前和对端通信成功的候选地址大家针对性去对症处理:。如果主机仅支持IPv6的地址,那就是全局的IPv6地址。对支持双栈的主机来说,RFC5245规范推荐使用IPv4地址作为默认候选地址。

3SDP解码

关于SDP的解码处理流程,全局部署场景和轻量级的部署场景的流程是一样的。Agent将针对每个媒体包含一个m行来表示它将要使用这个媒体。SDP中的媒体顺序和ICE相关。ICE将首先执行连接性检查第一个m行检查,接下来媒体流会进行传输。如果有媒体流的话,首先agent将媒体流置于SDP中,然后处理最重要的媒体流。

针对每个媒体流,每个候选地址将设置一个候选地址属性。关于此属性的构建需要遵从一定的规则,具体的规则参考RFC。属性将会负责传递IP地址和端口和候选地址所使用的传输协议,另外还有配合对端工作的ICE的一些属性:priority,foundation和component ID。除了以上这些属性参数因为,属性中还提供了关于候选地址的问题排查和其他函数功能,例如,候选地址类型和相关的传输地址。

基于agent之间的STUN连接性检查中使用的认证方式是短期认证机制,具体关于认证的处理在规范RFC5389中定义。相对于短期认证方式,RFC5389还定义了长期认证的方式。短期认证设定了一个时间限定,它仅在每个时间范围内有效。长期认证是通过订阅的方式实现认证。RFC章节有非常完整的介绍,读者可以查阅此章节细节获得更多内容。短期认证的处理机制是依赖于终端和服务器端之间通过协议使用用户和密码交互的方式实现。在ICE部署场景中,终端和服务器端则通过offer/answer的模式进行交互。安全用户名称是agent用户名称,通过冒号隔离。每个agent为了发送和接收消息,它使用密码来计算消息的完整性。用户名称和用户密码的交互通过ICE的ice-ufrag和ice-pwd属性来实现。用户名称和密码是为了保证其终端的认证以外,用户名称还有另外一个重要作用。Agent为了提供了针对媒体的安全设置,用户名称提供了针对媒体流的歧义和相关性检查。关于STUN用户名称的重要性的讨论,读者可以查阅RFC5245-B.4附录内容。

如果agent是一个轻量级的部署终端的话,agent必须在SDP中包含一个 ice-lite 的会话级属性。如果agent是全场景部署的终端的话,则一定不要包含此属性。

在SDP中添加默认的候选地址作为一个默认媒体目的地地址。RTP和RTCP的添加方式有所不同。如果媒体是基于RTP的媒体的话,把RTP候选地址中的IP地址和端口存入SDP中的c行和m行来完成。如果agent使用了RTCP的话,它必须使用a=rtcp属性对RTCP候选地址进行解码。具体RTCP的解码参考RFC.1章节。如果agent没有使用RTCP的话,agent必须说明未使用RTCP,具体的说明方式是通过b=RS:0和b=RR:0来表示。此SDP拓展是在RFC章节中声明。

当agent和一个非ICE端进行通信时,传输地址将是默认媒体目的地地址的话,这个传输地址必须作为候选地址出现在SDP中,可以以一个或者多个a=candidate行来表示。

ICE可提供拓展支持,拓展实现方式可通过在offer或answer中包含一系列的令牌来实现,agent使用其令牌可以确认ICE的拓展。具体来说,如果agent支持ICE拓展,它必须包含一个令牌,使用此令牌定义这个拓展,令牌定义在SDP中使用ice-options选项属性。以下是一个具体的包含ICE消息的SDP示例:

o=jdoe IN IP4 10.0.1.1

c=IN IP4 192.0.2.3

t=0 0

a=ice-pwd:asd88fgpdd777uzjYhagZg

a=ice-ufrag:8hhY // agnet 用户名称

m=audio 45664 RTP/AVP 0

b=RS:0 // 使用全部署场景

b=RR:0

a=rtpmap:0 PCMU/8000

a=candidate:1 1 UDP 10.0.1.1 8998 typ host

a=candidate:2 1 UDP 192.0.2.3 45664 typ srflx raddr

10.0.1.1 rport 8998

一旦agent已发送了offer或者an这些已变成了现实swer消息,它必须准备接收在每个候选地址上的STUN和媒体数据包。在全部署场景和轻量级部署场景中,媒体发送的流程有一定区别,更多关于不同部署场景中发送媒体包的讨论将在后续文章中流变仪做介绍。媒体包可被发送到一个候选地址中,此候选地址是在以前的offer或answer消息中出现的媒体默认目的地地址。

笔者通过以上章节的内容,重点介绍了发送初始化offer的一些流程,主要包括三个部分的内容,其中包括了全部署场景中的要求(采集候选地址,候选地址排序,移除冗余候选地址,选择默认候选地址),轻量级部署要求,SDP解码。

在下一个章节中,笔者将介绍接收初始化offer的处理流程。

参考资料:

关注公众号:asterisk-cn,获得有价值的Asterisk行业分享

Asterisk freepbx FreeSBC技术文档:

融合通信/IPPBX商业解决方案:

如何使用FreeSBC,技术分享群:

男性专科医院哪家好
成都白癜风哪个医院郊果好
成都白癜风医院怎么预约
成都包皮手术
相关资讯