Chapter 7:Sending Messages
SIP应用的核心操作就是收发消息。 跟第一章描述的一样,模块调用on_rx_request()和on_rx_response()来处理传入的消息。
本章介绍发送传出消息的基本方式,即不使用transaction和dialog。
下一个章节介绍 transaction是如何处理有状态的请求(包括传入和传出的请求)。
7.1 Sending Messages Overview
7.1.1 Creating Messages
PJSIP提供了多种API来创建和响应消息。下面是创建消息的一些方式:
#对于响应消息,最开始使用 pjsip_endpt_create_response()函数
#对于请求消息,可以使用函数 pjsip_endpt_create_request(),pjsip_endpt_create_request_from_hdr(), pjsip_endpt_create_ack(), pjsip_endpt_create_cancel()
#代理调用pjsip_endpt_create_request_fwd()和pjsip_endpt_create_response_fwd () ,可以根据要转发的传入消息,创建请求和响应消息。
# 或者你可以调用pjsip_endpt_create_tdata()建立传输缓冲区来创建请求和响应消息,调用 pjsip_msg_create()创建消息,调用pjsip_msg_add_hdr()或pjsip_msg_insert_first_hdr ()增加消息的头字段,或者消息体。
#更高层的模块(dialog layer)可以提供更多的方式来创建消息。这个描述在各个模块的文档中。
所有创建API的消息(除了低级别的 pjsip_endpt_create_tdata())都设置transmit buffer(pjsip_tx_data)的计数器为1,也就是说有时候应用程序(或堆栈)必须减少计数器来销毁transmit buffer。
所有发送API的消息必须减少transmit buffer的计数器,也就是说只要应用程序不对transmit buffer的引用计数器做任何事情,buffder就必须在发送后销毁。
7.1.2 Sending Messages
发送消息的最基本方式是调用pjsip_endpt_acquire_transport()和pjsip_transport_send ()。然而,要使其工作,必须知道发送消息的目标地址(即sockaddr,而不仅仅是hostname)。有下面几个步骤来获取消息和已存在的socket地址(决定使用哪种地址,RFC3263),这个函数级别太低了因此不能直接使用。
发送消息的核心API是pjsip_endpt_send_request_stateless()和pjsip_endpt_send_response ()。从传输层的自动处理上来说是很有用的两个函数,也是上层模块(transaction)使用的最基本的组成部分。
pjsip_endpt_send_request_stateless()用来发送请求消息,有以下步骤:
#根据Request-URI和Route header里的参数判断要连接的地址
#用RFC3263(SIP定位服务器)的步骤来解析目的服务器
#选择和建立连接服务器所需的传输
#修改传入的via header来反映当前所用的传输
#如果服务器不能使用当前的传输来连接,转移错误到下一个服务器/传输
pjsip_endpt_send_response ()函数用来发送响应消息,有以下步骤:
#按照RFC3261的18.2.2小节的步骤来选择使用何种传输,向哪个地址发送响应
#另外rport参数符合RFC3581
#使用选择的传输发送响应
#如果使用选择的传输发送响应失败,转移失败到下一个地址,必要时根据RFC3263解析服务器
因为消息可以异步发出(比如TCP连接后),这两种函数都提供通知应用程序传输状态的回调。这个回调还通知应用将发生的失败,应用就有机会去避免这种行为。
7.2 Function Reference
7.2.1 Sending Response
Base Functions
pj_status_t pjsip_endpt_create_response( pjsip_endpoint *endpt,
pjsip_rx_data *rdata,