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

📄 sip_util_proxy.c

📁 基于sip协议的网络电话源码
💻 C
字号:
/* $Id: sip_util_proxy.c 1121 2007-04-01 22:58:47Z bennylp $ *//*  * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */#include <pjsip/sip_util.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_errno.h>#include <pjsip/sip_msg.h>#include <pj/assert.h>#include <pj/ctype.h>#include <pj/except.h>#include <pj/pool.h>#include <pj/string.h>#include <pjlib-util/md5.h>/** * Clone the incoming SIP request or response message. A forwarding proxy * typically would need to clone the incoming SIP message before processing * the message. * * Once a transmit data is created, the reference counter is initialized to 1. * * @param endpt	    The endpoint instance. * @param rdata	    The incoming SIP message. * @param p_tdata   Pointer to receive the transmit data containing *		    the duplicated message. * * @return	    PJ_SUCCESS on success. */PJ_DEF(pj_status_t) pjsip_endpt_clone_msg( pjsip_endpoint *endpt,					   const pjsip_rx_data *rdata,					   pjsip_tx_data **p_tdata){    pjsip_tx_data *tdata;    pj_status_t status;    status = pjsip_endpt_create_tdata(endpt, &tdata);    if (status != PJ_SUCCESS)	return status;    tdata->msg = pjsip_msg_clone(tdata->pool, rdata->msg_info.msg);    pjsip_tx_data_add_ref(tdata);        *p_tdata = tdata;    return PJ_SUCCESS;}/* * Create new request message to be forwarded upstream to new destination URI  * in uri.  */PJ_DEF(pj_status_t) pjsip_endpt_create_request_fwd(pjsip_endpoint *endpt,						   pjsip_rx_data *rdata, 						   const pjsip_uri *uri,						   const pj_str_t *branch,						   unsigned options,						   pjsip_tx_data **p_tdata){    pjsip_tx_data *tdata;    pj_status_t status;    PJ_USE_EXCEPTION;    PJ_ASSERT_RETURN(endpt && rdata && p_tdata, PJ_EINVAL);    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG, 		     PJSIP_ENOTREQUESTMSG);    PJ_UNUSED_ARG(options);    /* Request forwarding rule in RFC 3261 section 16.6:     *     * For each target, the proxy forwards the request following these     * steps:     *      * 1.  Make a copy of the received request     * 2.  Update the Request-URI     * 3.  Update the Max-Forwards header field     * 4.  Optionally add a Record-route header field value     * 5.  Optionally add additional header fields     * 6.  Postprocess routing information     * 7.  Determine the next-hop address, port, and transport     * 8.  Add a Via header field value     * 9.  Add a Content-Length header field if necessary     * 10. Forward the new request     *     * Of these steps, we only do step 1-3, since the later will be     * done by application.     */    status = pjsip_endpt_create_tdata(endpt, &tdata);    if (status != PJ_SUCCESS)	return status;    /* Always increment ref counter to 1 */    pjsip_tx_data_add_ref(tdata);    /* Duplicate the request */    PJ_TRY {	pjsip_msg *dst;	const pjsip_msg *src = rdata->msg_info.msg;	const pjsip_hdr *hsrc;	/* Create the request */	tdata->msg = dst = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG);	/* Duplicate request method */	pjsip_method_copy(tdata->pool, &tdata->msg->line.req.method,			  &src->line.req.method);	/* Set request URI */	if (uri) {	    dst->line.req.uri = pjsip_uri_clone(tdata->pool, uri);	} else {	    dst->line.req.uri = pjsip_uri_clone(tdata->pool, src->line.req.uri);	}	/* Clone ALL headers */	hsrc = src->hdr.next;	while (hsrc != &src->hdr) {	    pjsip_hdr *hdst;	    /* If this is the top-most Via header, insert our own before	     * cloning the header.	     */	    if (hsrc == (pjsip_hdr*)rdata->msg_info.via) {		pjsip_via_hdr *hvia;		hvia = pjsip_via_hdr_create(tdata->pool);		if (branch)		    pj_strdup(tdata->pool, &hvia->branch_param, branch);		else {		    pj_str_t new_branch = pjsip_calculate_branch_id(rdata);		    pj_strdup(tdata->pool, &hvia->branch_param, &new_branch);		}		pjsip_msg_add_hdr(dst, (pjsip_hdr*)hvia);	    }	    /* Skip Content-Type and Content-Length as these would be 	     * generated when the the message is printed.	     */	    else if (hsrc->type == PJSIP_H_CONTENT_LENGTH ||		     hsrc->type == PJSIP_H_CONTENT_TYPE) {		hsrc = hsrc->next;		continue;	    }#if 0	    /* If this is the top-most Route header and it indicates loose	     * route, remove the header.	     */	    else if (hsrc == (pjsip_hdr*)rdata->msg_info.route) {		const pjsip_route_hdr *hroute = (const pjsip_route_hdr*) hsrc;		const pjsip_sip_uri *sip_uri;		if (!PJSIP_URI_SCHEME_IS_SIP(hroute->name_addr.uri) &&		    !PJSIP_URI_SCHEME_IS_SIPS(hroute->name_addr.uri))		{		    /* This is a bad request! */		    status = PJSIP_EINVALIDHDR;		    goto on_error;		}		sip_uri = (pjsip_sip_uri*) hroute->name_addr.uri;		if (sip_uri->lr_param) {		    /* Yes lr param is present, skip this Route header */		    hsrc = hsrc->next;		    continue;		}	    }#endif	    /* Clone the header */	    hdst = pjsip_hdr_clone(tdata->pool, hsrc);	    /* If this is Max-Forward header, decrement the value */	    if (hdst->type == PJSIP_H_MAX_FORWARDS) {		pjsip_max_fwd_hdr *hmaxfwd = (pjsip_max_fwd_hdr*)hdst;		--hmaxfwd->ivalue;	    }	    /* Append header to new request */	    pjsip_msg_add_hdr(dst, hdst);	    hsrc = hsrc->next;	}	/* 16.6.3:	 * If the copy does not contain a Max-Forwards header field, the         * proxy MUST add one with a field value, which SHOULD be 70.	 */	if (rdata->msg_info.max_fwd == NULL) {	    pjsip_max_fwd_hdr *hmaxfwd = 		pjsip_max_fwd_hdr_create(tdata->pool, 70);	    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hmaxfwd);	}	/* Clone request body */	if (src->body) {	    dst->body = pjsip_msg_body_clone(tdata->pool, src->body);	}    }    PJ_CATCH_ANY {	status = PJ_ENOMEM;	goto on_error;    }    PJ_END    /* Done */    *p_tdata = tdata;    return PJ_SUCCESS;on_error:    pjsip_tx_data_dec_ref(tdata);    return status;}PJ_DEF(pj_status_t) pjsip_endpt_create_response_fwd( pjsip_endpoint *endpt,						     pjsip_rx_data *rdata, 						     unsigned options,						     pjsip_tx_data **p_tdata){    pjsip_tx_data *tdata;    pj_status_t status;    PJ_USE_EXCEPTION;    PJ_UNUSED_ARG(options);    status = pjsip_endpt_create_tdata(endpt, &tdata);    if (status != PJ_SUCCESS)	return status;    pjsip_tx_data_add_ref(tdata);    PJ_TRY {	pjsip_msg *dst;	const pjsip_msg *src = rdata->msg_info.msg;	const pjsip_hdr *hsrc;	/* Create the request */	tdata->msg = dst = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG);	/* Clone the status line */	dst->line.status.code = src->line.status.code;	pj_strdup(tdata->pool, &dst->line.status.reason, 		  &src->line.status.reason);	/* Duplicate all headers */	hsrc = src->hdr.next;	while (hsrc != &src->hdr) {	    	    /* Skip Content-Type and Content-Length as these would be 	     * generated when the the message is printed.	     */	    if (hsrc->type == PJSIP_H_CONTENT_LENGTH ||		hsrc->type == PJSIP_H_CONTENT_TYPE) {		hsrc = hsrc->next;		continue;	    }	    /* Remove the first Via header */	    else if (hsrc == (pjsip_hdr*) rdata->msg_info.via) {		hsrc = hsrc->next;		continue;	    }	    pjsip_msg_add_hdr(dst, pjsip_hdr_clone(tdata->pool, hsrc));	    hsrc = hsrc->next;	}	/* Clone message body */	if (src->body)	    dst->body = pjsip_msg_body_clone(tdata->pool, src->body);    }    PJ_CATCH_ANY {	status = PJ_ENOMEM;	goto on_error;    }    PJ_END;    *p_tdata = tdata;    return PJ_SUCCESS;on_error:    pjsip_tx_data_dec_ref(tdata);    return status;}static void digest2str(const unsigned char digest[], char *output){    int i;    for (i = 0; i<16; ++i) {	pj_val_to_hex_digit(digest[i], output);	output += 2;    }}PJ_DEF(pj_str_t) pjsip_calculate_branch_id( pjsip_rx_data *rdata ){    pj_md5_context ctx;    pj_uint8_t digest[16];    pj_str_t branch;    /* Create branch ID for new request by calculating MD5 hash     * of the branch parameter in top-most Via header.     */    pj_md5_init(&ctx);    pj_md5_update(&ctx, (pj_uint8_t*)rdata->msg_info.via->branch_param.ptr,		  rdata->msg_info.via->branch_param.slen);    pj_md5_final(&ctx, digest);    branch.ptr = pj_pool_alloc(rdata->tp_info.pool, 			       32 + PJSIP_RFC3261_BRANCH_LEN);    pj_memcpy(branch.ptr, PJSIP_RFC3261_BRANCH_ID, PJSIP_RFC3261_BRANCH_LEN);    digest2str(digest, branch.ptr+PJSIP_RFC3261_BRANCH_LEN);    branch.slen = 32 + PJSIP_RFC3261_BRANCH_LEN;    return branch;}

⌨️ 快捷键说明

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