📄 sipua.c
字号:
/* Then send a call accept */
sip_status = sip_call_evt_accept(instance,
call,
dialog,
transaction,
subscription,
200,
"OK",
contact_response,
expires_response,
NULL,
body,/*对一个subscription请求发送一个最终的,实际的响应*/
NULL);/*此例程允许用户发送实际的,最终的响应(2XX响应)给关于特殊subscription的远端*/
if (sip_status != SIP_NORMAL) {
printf("The subscription can't be accepted, rc = %d.\n", sip_status);
} else {
printf("Subscription accepted...\n");
}
sip_msg_free_header(contact_response);/*此例程递归删除一个头和他的所有部分(URIs,参数,等等),如果引用计数器的值大于1,则减少引用计数器的值*/
sip_msg_free_header(expires_response);
for(index = 0; index < 5; index ++) {
char value[10];
sip_trans_t new_transaction;
sprintf(value, "value_%d", index);
subscription_state = sip_msg_new_subscription_state_header
(value, NULL, -1, -1, NULL, NULL);/*没找到相应的资料*/
sleep(1);
sip_status = sip_call_evt_notify(instance,
call,
dialog,
&new_transaction,
subscription,
subscription_state,
NULL,
body,
NULL);/*此例程发送NOTIFY请求*/
if (sip_status != SIP_NORMAL) {
printf("Notification can't be sent, rc = %d.\n", sip_status);
} else {
printf("Notify sent with status '%s'.\n", value);
}
sip_msg_free_header(subscription_state);/*此例程递归删除一个头和他的所有部分(URIs,参数,等等),如果引用计数器的值大于1,则减少引用计数器的值*/
}
return SIP_NORMAL;
}
/*
* FACILITY:
*
* The SIP call notify reception callback
*
* FORMAL PARAMETERS:
*
* instance : The SIP call instance
* call : The call identifier
* dialog : The dialog identifier
* transaction : The transaction identifier
* subscription : The subscription identifier
* subscription state : The state of the recieved event
* 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_evt_notify
(
sip_call_inst_t instance,
sip_call_t call,
sip_dialog_t dialog,
sip_trans_t transaction,
sip_subs_t subscription,
sip_msg_uri_t * request_uri,
sip_msg_header_t * event,
sip_msg_header_t * subscription_state,
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;
printf("NOTIFY received with status '%s' for event '%s'...",
subscription_state -> structured_header ->
content.subscription_state.value,
event -> structured_header -> content.event.event_type);
fflush(stdout);
/* Then send a 200 OK */
sip_status = sip_call_reply(instance,
call,
dialog,
transaction,
subscription,
200,
NULL,
NULL,
NULL,
SIP_FALSE,
NULL);/*对入请求,发送一个回复*/
/* 此例程允许用户回复入OPTIONS, EXTENSION, INFO,或 re-INVITE请求。*/
if (sip_status != SIP_NORMAL) {
printf("\nError sending the NOTIFY 200 OK, rc = %d.\n", sip_status);
} else {
printf(" 200 OK sent.\n");
}
if (unscuscribe_counter) {
unscuscribe_counter--;
if(!unscuscribe_counter) {
sip_msg_header_t * event;
sip_subs_t subscription_id;
sip_status = sip_call_evt_unsubscribe
(instance,
call,
dialog,
&transaction,
subscription,
SIP_CALL_RELEASE_GRACEFUL,/*从SIP角度看,正常释放。释放subscription 事件回调被调用*/
NULL,
NULL,
NULL);/*此例程发送SUBSCRIBE请求,对SUBSCRIBE消息创建的subscription,expire值为0。这将unsubscribe与此subscription相关的事件。否则,将仅仅释放本地资源*/
if(sip_status != SIP_NORMAL) {
printf("Error %d returned from sip_call_evt_unsubscribe\n", sip_status);
return(1);
} else {
printf("SUBSCRIBE(expires=0) = unsubscription sent...\n");
}
}
}
return SIP_NORMAL;
}
/*
* FACILITY:
*
* The SIP call event reception callback
*
* FORMAL PARAMETERS:
*
* instance : The SIP call handling instance
* call : The call identifier
* dialog : The dialog identifier
* event : The call event
* user_info : The user info
*
* RETURN VALUE:
*
* SIP_NORMAL : successful completion
*
*/
sip_status_t sip_call_on_event
(
sip_call_inst_t instance,
sip_call_t call,
sip_dialog_t dialog,
sip_call_event_t * event,
sip_user_info_t * user_info
)
{
switch(event->type)
{
case SIP_CALL_EVENT_LOCAL_SRV_ERROR:
printf("Local server error\n");
return SIP_CALL_TRANSFAIL;
case SIP_CALL_EVENT_ENUM_RES:
printf("Enum resolution error\n");
return SIP_CALL_TRANSFAIL;
case SIP_CALL_EVENT_TRANSACTION_DELETED:
printf("Transaction deleted\n");
if ( event->parameters.transaction_deleted.status != SIP_NORMAL )
return SIP_CALL_TRANSFAIL;
break;
case SIP_CALL_EVENT_DIALOG_DELETED:
printf("Dialog deleted\n");
if ( event->parameters.dialog_deleted.status != SIP_NORMAL )
return SIP_CALL_TRANSFAIL;
break;
default:
printf("Event type:%d received\n",event->type);
break;
}
return SIP_NORMAL;
}
/*
* FACILITY:
*
* call_uri
*
* ABSTRACT:
*
* The caller code, able to establish a call to the
* specified request URI.
*
* FORMAL PARAMETERS:
*
* sip_called_uri : The remote to call
* sip_ch_inst : The call-handling instance
* port : The local port number (to build the
* calling URI for the From: and Contact:
* headers.
*
* RETURN VALUE:
*
* None
*
*/
int call_uri(char * sip_called_uri,
sip_call_inst_t sip_ch_inst,
int port,
sip_bool_t do_body)/*很重要的函数*/
{/*此函数的流程,我的理解如下:
创建新的SIP URI结构
用给定的参数建立一个新的SIPFrom,Contact,To头
if (do_body){
用给定的参数来创建新的sdp_announcement_t结构
建造新的包含一个SDP announcement的sip msg body t结构
}
if(!subscribe_event_name) {
发送INVITE请求}else{
发送SUBSCRIBE请求}
释放一些变量的内存
if (cancel_delay){
延时一段时间
发送CANCEL请求
}
*/
sip_call_t call;
sip_dialog_t dialog;
sip_trans_t transaction;
sip_msg_header_t * from;
sip_msg_header_t * to;
sip_msg_header_t * contact;
sip_msg_uri_t * request_uri;
sip_msg_uri_t * calling_uri;
sip_status_t sip_rc;
sip_msg_error_t error;
sip_msg_body_t * sdp_body = 0;
sdp_announcement_t * sdp;
char hostname[50];
gethostname(hostname, 50);
calling_uri = sip_msg_new_sip_url("user",
hostname,
port,
NULL,
NULL,
SIP_MSG_NONE,/*缺省值,证明无METHOD*/
NULL,
-1,
NULL,
SIP_FALSE,
NULL,
NULL);/*此例程创建新的SIP URI结构,它包含了用给定的参数建造的"sip:" URL。此例程可以对存在的"sip:" URL更改参数*/
if(!calling_uri) {
sip_call_delete_instance(sip_ch_inst);/*此例程终止callhandling实例,并释放所有相关的对象(如呼叫)*/
printf("Unable to build the calling uri");
return(1);
}
if(interactive) {
printf("Press enter to start the call...\n");
getchar();
}
from = sip_msg_new_from_header(calling_uri, NULL, NULL, NULL, NULL);/*此例程用给定的参数建立一个新的SIPFrom头,或更改一个存在的头的参数*/
if(!from) {
printf("Unable to build the From: header\n");
return(1);
}
contact = sip_msg_new_contact_header(calling_uri, NULL, -1, -1, NULL, NULL);/*此例程用给定的参数建造一个新的SIPContact头,或更改一个存在的Contact头的参数*/
if(!contact) {
sip_call_delete_instance(sip_ch_inst);/*此例程终止callhandling实例,并释放所有相关的对象(如呼叫)*/
printf("Unable to build the Contact: header\n");
return(1);
}
request_uri = sip_msg_parse_uri(sip_called_uri, &error);/*此例程解析包含SIP URI的字符串为sip msg uri t 结构*/
if(!request_uri) {
printf("Syntax error near token '%s' in request URI\n",
error.unexpected_token);
return(1);
}
to = sip_msg_new_to_header(request_uri, NULL, NULL, NULL, NULL);/*此例程用给定的参数建造一个新的SIP TO头,或更改存在的头的参数*/
if(!to) {
printf("Unable to build the To: header\n");
return(1);
}
call = SIP_CALL_NO_CALL;
dialog = SIP_CALL_NO_DIALOG;
transaction = SIP_CALL_NO_TRANSACTION;
if(do_body) {
sdp = sdp_new_announcement(0,
"media",
"user1",
"12341234",
"2",
"IN",
"IP4",
"127.0.0.2",
NULL);/*用给定的参数来创建新的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,/*如果keep sdp参数为FALSE,此SDP announcement自动和sip msg body t结构同时被删除*/
SIP_FALSE, NULL);/*此例程建造新的包含一个SDP announcement的sip msg body t结构。作为一个参数给出的SDP announcement将不被复制(新的body仅仅指向源SDP announcement)*/
}
if(!subscribe_event_name) {
/* Normal INVITE case */
sip_rc = sip_call_initiate(sip_ch_inst,
&call,
&dialog,
&transaction,
request_uri,
from,
to,
contact,
NULL,
sdp_body,
NULL);/*此例程发送INVITE请求,初始化出呼叫*/
if(sip_rc != SIP_NORMAL) {
printf("Error %d returned from sip_call_initiate\n", sip_rc);
return(1);
} else {
printf("Initiate call ongoing...\n");
}
} else {
/* SUBSCRIBE case */
sip_msg_header_t * event;
sip_subs_t subscription_id;
event = sip_msg_new_event_header/*没找到相关资料*/
(subscribe_event_name, NULL, NULL, NULL);
if(!event) {
printf("Error returned from sip_msg_new_event_header\n");
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -