⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_util.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    pj_assert(rdata->msg_info.msg->type==PJSIP_RESPONSE_MSG &&	      rdata->msg_info.msg->line.status.code >= 300);    /* Initialize return value to NULL. */    *ack_tdata = NULL;    /* The original INVITE message. */    invite_msg = tdata->msg;    /* Get the headers from original INVITE request. */#   define FIND_HDR(m,HNAME) pjsip_msg_find_hdr(m, PJSIP_H_##HNAME, NULL)    from_hdr = (const pjsip_from_hdr*) FIND_HDR(invite_msg, FROM);    PJ_ASSERT_ON_FAIL(from_hdr != NULL, goto on_missing_hdr);    to_hdr = (const pjsip_to_hdr*) FIND_HDR(invite_msg, TO);    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr);    cid_hdr = (const pjsip_cid_hdr*) FIND_HDR(invite_msg, CALL_ID);    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr);    cseq_hdr = (const pjsip_cseq_hdr*) FIND_HDR(invite_msg, CSEQ);    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr);#   undef FIND_HDR    /* Create new request message from the headers. */    status = pjsip_endpt_create_request_from_hdr(endpt, 						 &pjsip_ack_method,						 tdata->msg->line.req.uri,						 from_hdr, to_hdr,						 NULL, cid_hdr,						 cseq_hdr->cseq, NULL,						 &ack);    if (status != PJ_SUCCESS)	return status;    /* Update tag in To header with the one from the response (if any). */    to = (pjsip_to_hdr*) pjsip_msg_find_hdr(ack->msg, PJSIP_H_TO, NULL);    pj_strdup(ack->pool, &to->tag, &rdata->msg_info.to->tag);    /* Clear Via headers in the new request. */    while ((via=pjsip_msg_find_hdr(ack->msg, PJSIP_H_VIA, NULL)) != NULL)	pj_list_erase(via);    /* Must contain single Via, just as the original INVITE. */    hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_VIA, NULL);    pjsip_msg_insert_first_hdr( ack->msg, pjsip_hdr_clone(ack->pool,hdr) );    /* If the original INVITE has Route headers, those header fields MUST      * appear in the ACK.     */    hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, NULL);    while (hdr != NULL) {	pjsip_msg_add_hdr( ack->msg, pjsip_hdr_clone(ack->pool, hdr) );	hdr = hdr->next;	if (hdr == &invite_msg->hdr)	    break;	hdr = pjsip_msg_find_hdr( invite_msg, PJSIP_H_ROUTE, hdr);    }    /* We're done.     * "tdata" parameter now contains the ACK message.     */    *ack_tdata = ack;    return PJ_SUCCESS;on_missing_hdr:    if (ack)	pjsip_tx_data_dec_ref(ack);    return PJSIP_EMISSINGHDR;}/* * Construct CANCEL request for the previously sent request, according to * chapter 9.1 of RFC3261. */PJ_DEF(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,					       const pjsip_tx_data *req_tdata,					       pjsip_tx_data **p_tdata){    pjsip_tx_data *cancel_tdata = NULL;    const pjsip_from_hdr *from_hdr;    const pjsip_to_hdr *to_hdr;    const pjsip_cid_hdr *cid_hdr;    const pjsip_cseq_hdr *cseq_hdr;    const pjsip_hdr *hdr;    pjsip_hdr *via;    pj_status_t status;    /* The transmit buffer must INVITE request. */    PJ_ASSERT_RETURN(req_tdata->msg->type == PJSIP_REQUEST_MSG &&		     req_tdata->msg->line.req.method.id == PJSIP_INVITE_METHOD,		     PJ_EINVAL);    /* Get the headers from original INVITE request. */#   define FIND_HDR(m,HNAME) pjsip_msg_find_hdr(m, PJSIP_H_##HNAME, NULL)    from_hdr = (const pjsip_from_hdr*) FIND_HDR(req_tdata->msg, FROM);    PJ_ASSERT_ON_FAIL(from_hdr != NULL, goto on_missing_hdr);    to_hdr = (const pjsip_to_hdr*) FIND_HDR(req_tdata->msg, TO);    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr);    cid_hdr = (const pjsip_cid_hdr*) FIND_HDR(req_tdata->msg, CALL_ID);    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr);    cseq_hdr = (const pjsip_cseq_hdr*) FIND_HDR(req_tdata->msg, CSEQ);    PJ_ASSERT_ON_FAIL(to_hdr != NULL, goto on_missing_hdr);#   undef FIND_HDR    /* Create new request message from the headers. */    status = pjsip_endpt_create_request_from_hdr(endpt, 						 &pjsip_cancel_method,						 req_tdata->msg->line.req.uri,						 from_hdr, to_hdr,						 NULL, cid_hdr,						 cseq_hdr->cseq, NULL,						 &cancel_tdata);    if (status != PJ_SUCCESS)	return status;    /* Clear Via headers in the new request. */    while ((via=pjsip_msg_find_hdr(cancel_tdata->msg, PJSIP_H_VIA, NULL)) != NULL)	pj_list_erase(via);    /* Must only have single Via which matches the top-most Via in the      * request being cancelled.      */    hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_VIA, NULL);    if (hdr) {	pjsip_msg_insert_first_hdr(cancel_tdata->msg, 				   pjsip_hdr_clone(cancel_tdata->pool, hdr));    }    /* If the original request has Route header, the CANCEL request must also     * has exactly the same.     * Copy "Route" header from the request.     */    hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_ROUTE, NULL);    while (hdr != NULL) {	pjsip_msg_add_hdr(cancel_tdata->msg, 			  pjsip_hdr_clone(cancel_tdata->pool, hdr));	hdr = hdr->next;	if (hdr != &req_tdata->msg->hdr)	    hdr = pjsip_msg_find_hdr(req_tdata->msg, PJSIP_H_ROUTE, hdr);	else	    break;    }    /* Done.     * Return the transmit buffer containing the CANCEL request.     */    *p_tdata = cancel_tdata;    return PJ_SUCCESS;on_missing_hdr:    if (cancel_tdata)	pjsip_tx_data_dec_ref(cancel_tdata);    return PJSIP_EMISSINGHDR;}/* * Find which destination to be used to send the request message, based * on the request URI and Route headers in the message. The procedure * used here follows the guidelines on sending the request in RFC 3261 * chapter 8.1.2. */PJ_DEF(pj_status_t) pjsip_get_request_dest(const pjsip_tx_data *tdata,					   pjsip_host_info *dest_info ){    const pjsip_uri *target_uri;    const pjsip_route_hdr *first_route_hdr;        PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG, 		     PJSIP_ENOTREQUESTMSG);    PJ_ASSERT_RETURN(dest_info != NULL, PJ_EINVAL);    /* Get the first "Route" header from the message.     */    first_route_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);    if (first_route_hdr) {	target_uri = first_route_hdr->name_addr.uri;    } else {	target_uri = tdata->msg->line.req.uri;    }    /* The target URI must be a SIP/SIPS URL so we can resolve it's address.     * Otherwise we're in trouble (i.e. there's no host part in tel: URL).     */    pj_bzero(dest_info, sizeof(*dest_info));    if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) {	pjsip_uri *uri = (pjsip_uri*) target_uri;	const pjsip_sip_uri *url=(const pjsip_sip_uri*)pjsip_uri_get_uri(uri);	dest_info->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE);	pj_strdup(tdata->pool, &dest_info->addr.host, &url->host);        dest_info->addr.port = url->port;	dest_info->type =             pjsip_transport_get_type_from_name(&url->transport_param);    } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) {	pjsip_uri *uri = (pjsip_uri*) target_uri;	const pjsip_sip_uri *url=(const pjsip_sip_uri*)pjsip_uri_get_uri(uri);	pj_strdup(tdata->pool, &dest_info->addr.host, &url->host);	dest_info->addr.port = url->port;	dest_info->type =             pjsip_transport_get_type_from_name(&url->transport_param);	dest_info->flag = 	    pjsip_transport_get_flag_from_type(dest_info->type);    } else {        pj_assert(!"Unsupported URI scheme!");	PJ_TODO(SUPPORT_REQUEST_ADDR_RESOLUTION_FOR_TEL_URI);	return PJSIP_EINVALIDSCHEME;    }    return PJ_SUCCESS;}/* * Process route-set found in the request and calculate * the destination to be used to send the request message, based * on the request URI and Route headers in the message. The procedure * used here follows the guidelines on sending the request in RFC 3261 * chapter 8.1.2. */PJ_DEF(pj_status_t) pjsip_process_route_set(pjsip_tx_data *tdata,					    pjsip_host_info *dest_info ){    const pjsip_uri *new_request_uri, *target_uri;    const pjsip_name_addr *topmost_route_uri;    pjsip_route_hdr *first_route_hdr, *last_route_hdr;        PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG, 		     PJSIP_ENOTREQUESTMSG);    PJ_ASSERT_RETURN(dest_info != NULL, PJ_EINVAL);    /* Find the first and last "Route" headers from the message. */    last_route_hdr = first_route_hdr = 	pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL);    if (first_route_hdr) {	topmost_route_uri = &first_route_hdr->name_addr;	while (last_route_hdr->next != (void*)&tdata->msg->hdr) {	    pjsip_route_hdr *hdr;	    hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE,                                      last_route_hdr->next);	    if (!hdr)		break;	    last_route_hdr = hdr;	}    } else {	topmost_route_uri = NULL;    }    /* If Route headers exist, and the first element indicates loose-route,     * the URI is taken from the Request-URI, and we keep all existing Route     * headers intact.     * If Route headers exist, and the first element DOESN'T indicate loose     * route, the URI is taken from the first Route header, and remove the     * first Route header from the message.     * Otherwise if there's no Route headers, the URI is taken from the     * Request-URI.     */    if (topmost_route_uri) {	pj_bool_t has_lr_param;	if (PJSIP_URI_SCHEME_IS_SIP(topmost_route_uri) ||	    PJSIP_URI_SCHEME_IS_SIPS(topmost_route_uri))	{	    const pjsip_sip_uri *url = 		pjsip_uri_get_uri((void*)topmost_route_uri);	    has_lr_param = url->lr_param;	} else {	    has_lr_param = 0;	}	if (has_lr_param) {	    new_request_uri = tdata->msg->line.req.uri;	    /* We shouldn't need to delete topmost Route if it has lr param.	     * But seems like it breaks some proxy implementation, so we	     * delete it anyway.	     */	    /*	    pj_list_erase(first_route_hdr);	    if (first_route_hdr == last_route_hdr)		last_route_hdr = NULL;	    */	} else {	    new_request_uri = pjsip_uri_get_uri((void*)topmost_route_uri);	    pj_list_erase(first_route_hdr);	    if (first_route_hdr == last_route_hdr)		last_route_hdr = NULL;	}	target_uri = (pjsip_uri*)topmost_route_uri;    } else {	target_uri = new_request_uri = tdata->msg->line.req.uri;    }    /* The target URI must be a SIP/SIPS URL so we can resolve it's address.     * Otherwise we're in trouble (i.e. there's no host part in tel: URL).     */    pj_bzero(dest_info, sizeof(*dest_info));    if (PJSIP_URI_SCHEME_IS_SIPS(target_uri)) {	pjsip_uri *uri = (pjsip_uri*) target_uri;	const pjsip_sip_uri *url=(const pjsip_sip_uri*)pjsip_uri_get_uri(uri);	dest_info->flag |= (PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_RELIABLE);	pj_strdup(tdata->pool, &dest_info->addr.host, &url->host);        dest_info->addr.port = url->port;	dest_info->type =             pjsip_transport_get_type_from_name(&url->transport_param);    } else if (PJSIP_URI_SCHEME_IS_SIP(target_uri)) {	pjsip_uri *uri = (pjsip_uri*) target_uri;	const pjsip_sip_uri *url=(const pjsip_sip_uri*)pjsip_uri_get_uri(uri);	pj_strdup(tdata->pool, &dest_info->addr.host, &url->host);	dest_info->addr.port = url->port;	dest_info->type =             pjsip_transport_get_type_from_name(&url->transport_param);	dest_info->flag = 	    pjsip_transport_get_flag_from_type(dest_info->type);    } else {        pj_assert(!"Unsupported URI scheme!");	PJ_TODO(SUPPORT_REQUEST_ADDR_RESOLUTION_FOR_TEL_URI);	return PJSIP_EINVALIDSCHEME;    }    /* If target URI is different than request URI, replace      * request URI add put the original URI in the last Route header.     */    if (new_request_uri && new_request_uri!=tdata->msg->line.req.uri) {	pjsip_route_hdr *route = pjsip_route_hdr_create(tdata->pool);	route->name_addr.uri = pjsip_uri_get_uri(tdata->msg->line.req.uri);	if (last_route_hdr)	    pj_list_insert_after(last_route_hdr, route);	else	    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)route);	tdata->msg->line.req.uri = (pjsip_uri*)new_request_uri;    }    /* Success. */    return PJ_SUCCESS;  }/* Transport callback for sending stateless request.  * This is one of the most bizzare function in pjsip, so * good luck if you happen to debug this function!! */static void stateless_send_transport_cb( void *token,					 pjsip_tx_data *tdata,					 pj_ssize_t sent ){    pjsip_send_state *stateless_data = token;    PJ_UNUSED_ARG(tdata);    pj_assert(tdata == stateless_data->tdata);    for (;;) {	pj_status_t status;	pj_bool_t cont;	pj_sockaddr_t *cur_addr;	pjsip_transport_type_e cur_addr_type;	int cur_addr_len;	pjsip_via_hdr *via;	if (sent == -PJ_EPENDING) {	    /* This is the initial process.	     * When the process started, this function will be called by	     * stateless_send_resolver_callback() with sent argument set to	     * -PJ_EPENDING.	     */	    cont = PJ_TRUE;	} else {	    /* There are two conditions here:	     * (1) Message is sent (i.e. sent > 0),	     * (2) Failure (i.e. sent <= 0)	     */	    cont = (sent > 0) ? PJ_FALSE :		   (stateless_data->cur_addr<stateless_data->addr.count-1);	    if (stateless_data->app_cb) {		(*stateless_data->app_cb)(stateless_data, sent, &cont);	    } else {		/* Doesn't have application callback.		 * Terminate the process.		 */		cont = PJ_FALSE;	    }	}	/* Finished with this transport. */	if (stateless_data->cur_transport) {	    pjsip_transport_dec_ref(stateless_data->cur_transport);	    stateless_data->cur_transport = NULL;	}	/* Done if application doesn't want to continue. */	if (sent > 0 || !cont) {	    pjsip_tx_data_dec_ref(tdata);	    return;	}	/* Try next address, if any, and only when this is not the 	 * first invocation. 	 */	if (sent != -PJ_EPENDING) {	    stateless_data->cur_addr++;	}	/* Have next address? */	if (stateless_data->cur_addr >= stateless_data->addr.count) {	    /* This only happens when a rather buggy application has	     * sent 'cont' to PJ_TRUE when the initial value was PJ_FALSE.	     * In this case just stop the processing; we don't need to	     * call the callback again as application has been informed	     * before.	     */	    pjsip_tx_data_dec_ref(tdata);	    return;	}	/* Keep current server address information handy. */	cur_addr = &stateless_data->addr.entry[stateless_data->cur_addr].addr;	cur_addr_type = stateless_data->addr.entry[stateless_data->cur_addr].type;	cur_addr_len = stateless_data->addr.entry[stateless_data->cur_addr].addr_len;	/* Acquire transport. */	status = pjsip_endpt_acquire_transport( stateless_data->endpt,						cur_addr_type,						cur_addr,						cur_addr_len,						&tdata->tp_sel,						&stateless_data->cur_transport);	if (status != PJ_SUCCESS) {	    sent = -status;	    continue;	}	/* Modify Via header. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -