📄 sipua.c
字号:
/* @@ WARNING: This example is automatically included in the user
@@ documentation. (Note: The lines containing '@@' are removed
@@ automatically). */
/*
* WARNING
*
* This sample application uses the sleep() system call
* in callback routines, for the sake of simplicity. This
* allows simple coding of the sample, to introcuce user
* delays or call duration.
*
* BUT, a real-world application should never stop during
* a callback routine. During the processing of a callback,
* no other indications can be delivered, incoming SIP
* messages are stored in the SIP stack and cause congestion.
*
* If you need to stop or wait for I/O before answering the
* request, you must return from the callback and trigger
* an asynchronous mechanisn (threads, timers, ...) to answer
* the request at a later time.
*/
/*
* WARNING
*
*这个例子在回调例程中使用了sleep()系统调用,这是出于简单性的考虑
*这使此例子简单化,来说明用户延时或呼叫延时。
*
*
*
*但是,在真实的应用中,不应该在回调例程中停止。在回调的处理中,
*没有其他indications可以传递,入SIP消息将存储在SIP栈中,(如果此时停止)这将引起拥塞。
*
*
*
*
*如果你需要停止或等待I/O,之后才应答此请求,你必须从回调
*中返回,并触发异步机制(线程,定时器。。。)来在以后应答请求
*/
#include <string.h>
#include <stdio.h>
#include <sys/signal.h>
#include <pthread.h>
#include <arpa/inet.h>
#include "sip_api.h"
sip_bool_t sip_exit = SIP_FALSE;
sip_bool_t interactive = SIP_FALSE;
sip_bool_t no_bye = SIP_FALSE;
sip_bool_t no_delay = SIP_FALSE;
sip_bool_t auto_exit = SIP_TRUE;
int cancel_delay = 0;
int uas_bye_delay = 0;
int uas_invite_delay = 0;
char * subscribe_event_name = NULL;
int unscuscribe_counter = 0;
/*
* FACILITY:
*
* sip_call_on_initiate
*
* ABSTRACT:
*
* The SIP call initiate reception callback
*
* FORMAL PARAMETERS:
*
* instance : The SIP call instance
* call : The call identifier
* dialog : The dialog identifier
* transaction : The transaction identifier
* request_uri : The request URI to forward the INVITE
* from : The from header
* to : The to header
* contact : The contact header
* request : Additional headers in the INVITE
* body : The INVITE body
* user_info : The user info
*
* RETURN VALUE:
*
* SIP_NORMAL : successful completion
*
*/
sip_status_t sip_call_on_initiate
(
sip_call_inst_t instance,
sip_call_t call,
sip_dialog_t dialog,
sip_trans_t transaction,
sip_msg_uri_t * request_uri,
sip_msg_header_t * from,
sip_msg_header_t * to,
sip_msg_header_t * contact,
sip_msg_header_vector_t * request,
sip_msg_body_t * body,
sip_user_info_t * user_info
)
{
sip_status_t sip_status;
sip_msg_header_t * contact_response;
char from_string[255];
if(sip_msg_print_header(from, from_string, 255, SIP_FALSE, NULL) > 0) {
printf("Call received, %s.\n",from_string);
}/*此函数在parser中出现,功能为编码SIP头结构为包含等价SIP头的字符串*/
if(uas_invite_delay) {
printf("Adding a %d sec delay before answering 180 Ringing\n",
uas_invite_delay);
sleep(uas_invite_delay);
}
/* We first reply with a 180 ringing */
sip_status = sip_call_progress(instance,
call,
dialog,
transaction,
180,
"Ringing",
NULL,
NULL,
SIP_FALSE,/*不需要可靠性*/
NULL);/*此例程允许用户发送临时响应(1XX响应)。如果响应需要可靠性,SIPcallhandling级等待从远端的PRACK请求,之后才允许更多的响应被发送。此例程仅仅支持INVITE请求。*/
if (sip_status != SIP_NORMAL)
{
printf("Error %d in sending a call in progress\n", sip_status);
return SIP_NORMAL;
}
if(!no_delay) {
printf("Waiting 3 seconds before accepting the call...\n");
sleep(3);
}
contact_response = sip_msg_new_contact_header
(request_uri, NULL, -1, -1, NULL, NULL);
/*此例程用给定的参数建造一个新的SIPContact头,或更改一个存在的Contact头的参数*/
if(!contact_response) {
printf("Unable to build the Contact: header\n");
exit(1);
}
if(!body) {// 1
sip_msg_body_t * sdp_body;
sdp_announcement_t * sdp;
sdp = sdp_new_announcement(0,
"media",
"user1",
"12341234",
"2",
"IN",
"IP4",
"127.0.0.2",
NULL);/*创建新的SDP announcement.*/
/*此例程在parser内说明,用给定的参数来创建新的sdp_announcement_t结构。这些参数用于建立2个强制域(session_name and origin)*/
if(!sdp) {
printf("Unable to build SDP announcement\n");
exit(1);
}
sdp_body = sip_msg_new_sdp_body(sdp,
SIP_FALSE, NULL);
/*此例程在parser内说明,此例程创建新的SDP体*/
/*建造新的包含一个SDP announcement的sip msg body t结构。作为一个参数给出的SDP announcement将不被复制(新的body仅仅指向源SDP announcement)*/
/* Then send a 200 OK */
sip_status = sip_call_accept(instance,
call,
dialog,
transaction,
200,
"OK",
contact_response,
NULL,
sdp_body,
NULL);/*此例程允许用户发送实际的,最终的响应(2XX响应)给远端。*/
sip_msg_free_body(sdp_body);/*此例程在parser内说明,删除一个体*/
/* 此例程递归地删除SIP体结构和它所有部分(SDP announcement等等),当引用计数器的值大于1时,减少它的值*/
} else {// 1
/* Then send a 200 OK */
sip_status = sip_call_accept(instance,
call,
dialog,
transaction,
200,
"OK",
contact_response,
NULL,
body,
NULL);/*此例程允许用户发送实际的,最终的响应(2XX响应)给远端。*/
}// end 1
if (sip_status != SIP_NORMAL)
{
printf("The call can't be accepted, rc = %d.\n", sip_status);
} else {
printf("Call accepted...\n");
}
sip_msg_free_header(contact_response);
/*此例程在parser内说明,删除给定的头*/
/*此例程递归删除一个头和他的所有部分(URIs,参数,等等),如果引用计数器的值大于1,则减少引用计数器的值*/
return SIP_NORMAL;
}
/*
* FACILITY:
*
* sip_call_on_connect
*
* ABSTRACT:
*
* The SIP call connect reception callback
*
* FORMAL PARAMETERS:
*
* instance : The SIP call handling instance
* call : The call identifier
* dialog : The dialog identifier
* transaction : The transaction identifier
* request_uri : The request URI to forward the INVITE
* request : The request headers
* body : The message body
* user_info : The user info
*
* RETURN VALUE:
*
* SIP_NORMAL : successful completion
*
*/
sip_status_t sip_call_on_connect
(
sip_call_inst_t instance,
sip_call_t call,
sip_dialog_t dialog,
sip_trans_t transaction,
sip_msg_uri_t * request_uri,
sip_msg_header_vector_t * request,
sip_msg_body_t * body,
sip_user_info_t * user_info
)
{
printf("The call is established\n");
if(uas_bye_delay) {// 2
sip_trans_t new_trans;
printf("Waiting %d second before releasing the call\n",
uas_bye_delay);
sleep(uas_bye_delay);
printf("Releasing the call.\n");
/* send a CANCEL request *//*依靠呼叫状态,SIPcallhandling级处理用户请求也不尽相同*/
/*为什么这里就一定肯定为发送CANCEL呢*/
sip_call_release(instance,
call,
dialog,
&new_trans,
NULL,
NULL,
SIP_CALL_RELEASE_AUTOMATIC,/*从SIP角度看,正常释放。释放呼叫事件回调不被调用*/
user_info);/*释放特定呼叫,此例程较复杂,可查看自己的读书笔记*/
}// end 2
return SIP_NORMAL;
}
/*
* FACILITY:
*
* sip_call_on_progress
*
* ABSTRACT:
*
* The SIP call Ringing reception callback
*
* FORMAL PARAMETERS:
*
* instance : The SIP call instance
* call : The call identifier
* dialog : The dialog identifier
* transaction : The transaction identifier
* status_code : The status code (1xx) received in the response
* reason_phrase : The character string in the received status line
* response : Additional headers in the response
* body : The received body
* user_info : The user info
*
* RETURN VALUE:
*
* SIP_NORMAL : successful completion
*
*/
sip_status_t sip_call_on_progress
(
sip_call_inst_t instance,
sip_call_t call,
sip_dialog_t dialog,
sip_trans_t transaction,
sip_uint32_t status_code,
char * reason_phrase,
sip_msg_header_vector_t * response,
sip_msg_body_t * body,
sip_user_info_t * user_info
)
{
printf("Progressing: %s...\n", reason_phrase);
return SIP_NORMAL;
}
/*
* FACILITY:
*
* sip_call_on_accept
*
* ABSTRACT:
*
* The SIP call accept reception callback
*
* FORMAL PARAMETERS:
*
* instance : The SIP call instance
* call : The call identifier
* dialog : The dialog identifier
* transaction : The transaction identifier
* status_code : The status code (200) received in the response
* reason_phrase : The character string in the received status line
* response : Additional headers in the response
* body : The received body
* user_info : The user info
*
* RETURN VALUE:
*
* SIP_NORMAL : successful completion
*
*/
sip_status_t sip_call_on_accept
(
sip_call_inst_t instance,
sip_call_t call,
sip_dialog_t dialog,
sip_trans_t transaction,
sip_uint32_t status_code,
char * reason_phrase,
sip_msg_header_vector_t * response,
sip_msg_body_t * body,
sip_user_info_t * user_info
)
{
sip_trans_t new_trans;
printf("The call has been accepted\n");
/* send ACK request */
sip_call_connect(instance,
call,
dialog,
transaction,
NULL,
NULL,
NULL);/*在接收了最终的成功响应后,发送ACK请求*/
/*此例程仅支持INVITE请求*/
if(!no_bye) {// 3
printf("Waiting 3 seconds before releasing the call...\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -