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

📄 sip_util.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: sip_util.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_transport.h>#include <pjsip/sip_msg.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_event.h>#include <pjsip/sip_transaction.h>#include <pjsip/sip_module.h>#include <pjsip/sip_errno.h>#include <pj/log.h>#include <pj/string.h>#include <pj/guid.h>#include <pj/pool.h>#include <pj/except.h>#include <pj/rand.h>#include <pj/assert.h>#include <pj/errno.h>#define THIS_FILE    "endpoint"static const char *event_str[] = {    "UNIDENTIFIED",    "TIMER",    "TX_MSG",    "RX_MSG",    "TRANSPORT_ERROR",    "TSX_STATE",    "USER",};static pj_str_t str_TEXT = { "text", 4},		str_PLAIN = { "plain", 5 };/* * Initialize transmit data (msg) with the headers and optional body. * This will just put the headers in the message as it is. Be carefull * when calling this function because once a header is put in a message,  * it CAN NOT be put in other message until the first message is deleted,  * because the way the header is put in the list. * That's why the session will shallow_clone it's headers before calling * this function. */static void init_request_throw( pjsip_endpoint *endpt,                                pjsip_tx_data *tdata, 				pjsip_method *method,				pjsip_uri *param_target,				pjsip_from_hdr *param_from,				pjsip_to_hdr *param_to, 				pjsip_contact_hdr *param_contact,				pjsip_cid_hdr *param_call_id,				pjsip_cseq_hdr *param_cseq, 				const pj_str_t *param_text){    pjsip_msg *msg;    pjsip_msg_body *body;    pjsip_via_hdr *via;    const pjsip_hdr *endpt_hdr;    /* Create the message. */    msg = tdata->msg = pjsip_msg_create(tdata->pool, PJSIP_REQUEST_MSG);    /* Init request URI. */    pj_memcpy(&msg->line.req.method, method, sizeof(*method));    msg->line.req.uri = param_target;    /* Add additional request headers from endpoint. */    endpt_hdr = pjsip_endpt_get_request_headers(endpt)->next;    while (endpt_hdr != pjsip_endpt_get_request_headers(endpt)) {	pjsip_hdr *hdr = pjsip_hdr_shallow_clone(tdata->pool, endpt_hdr);	pjsip_msg_add_hdr( tdata->msg, hdr );	endpt_hdr = endpt_hdr->next;    }    /* Add From header. */    if (param_from->tag.slen == 0)	pj_create_unique_string(tdata->pool, &param_from->tag);    pjsip_msg_add_hdr(msg, (void*)param_from);    /* Add To header. */    pjsip_msg_add_hdr(msg, (void*)param_to);    /* Add Contact header. */    if (param_contact) {	pjsip_msg_add_hdr(msg, (void*)param_contact);    }    /* Add Call-ID header. */    pjsip_msg_add_hdr(msg, (void*)param_call_id);    /* Add CSeq header. */    pjsip_msg_add_hdr(msg, (void*)param_cseq);    /* Add a blank Via header in the front of the message. */    via = pjsip_via_hdr_create(tdata->pool);    via->rport_param = 0;    pjsip_msg_insert_first_hdr(msg, (void*)via);    /* Add header params as request headers */    if (PJSIP_URI_SCHEME_IS_SIP(param_target) || 	PJSIP_URI_SCHEME_IS_SIPS(param_target))     {	pjsip_sip_uri *uri = (pjsip_sip_uri*) pjsip_uri_get_uri(param_target);	pjsip_param *hparam;	hparam = uri->header_param.next;	while (hparam != &uri->header_param) {	    pjsip_generic_string_hdr *hdr;	    hdr = pjsip_generic_string_hdr_create(tdata->pool, 						  &hparam->name,						  &hparam->value);	    pjsip_msg_add_hdr(msg, (pjsip_hdr*)hdr);	    hparam = hparam->next;	}    }    /* Create message body. */    if (param_text) {	body = pj_pool_calloc(tdata->pool, 1, sizeof(pjsip_msg_body));	body->content_type.type = str_TEXT;	body->content_type.subtype = str_PLAIN;	body->data = pj_pool_alloc(tdata->pool, param_text->slen );	pj_memcpy(body->data, param_text->ptr, param_text->slen);	body->len = param_text->slen;	body->print_body = &pjsip_print_text_body;	msg->body = body;    }    PJ_LOG(5,(THIS_FILE, "%s created.", 			 pjsip_tx_data_get_info(tdata)));}/* * Create arbitrary request. */PJ_DEF(pj_status_t) pjsip_endpt_create_request(  pjsip_endpoint *endpt, 						 const pjsip_method *method,						 const pj_str_t *param_target,						 const pj_str_t *param_from,						 const pj_str_t *param_to, 						 const pj_str_t *param_contact,						 const pj_str_t *param_call_id,						 int param_cseq, 						 const pj_str_t *param_text,						 pjsip_tx_data **p_tdata){    pjsip_uri *target;    pjsip_tx_data *tdata;    pjsip_from_hdr *from;    pjsip_to_hdr *to;    pjsip_contact_hdr *contact;    pjsip_cseq_hdr *cseq = NULL;    /* = NULL, warning in VC6 */    pjsip_cid_hdr *call_id;    pj_str_t tmp;    pj_status_t status;    PJ_USE_EXCEPTION;    status = pjsip_endpt_create_tdata(endpt, &tdata);    if (status != PJ_SUCCESS)	return status;    /* Init reference counter to 1. */    pjsip_tx_data_add_ref(tdata);    PJ_TRY {	/* Request target. */	pj_strdup_with_null(tdata->pool, &tmp, param_target);	target = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 0);	if (target == NULL) {	    status = PJSIP_EINVALIDREQURI;	    goto on_error;	}	/* From */	from = pjsip_from_hdr_create(tdata->pool);	pj_strdup_with_null(tdata->pool, &tmp, param_from);	from->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 				     PJSIP_PARSE_URI_AS_NAMEADDR);	if (from->uri == NULL) {	    status = PJSIP_EINVALIDHDR;	    goto on_error;	}	pj_create_unique_string(tdata->pool, &from->tag);	/* To */	to = pjsip_to_hdr_create(tdata->pool);	pj_strdup_with_null(tdata->pool, &tmp, param_to);	to->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen, 				   PJSIP_PARSE_URI_AS_NAMEADDR);	if (to->uri == NULL) {	    status = PJSIP_EINVALIDHDR;	    goto on_error;	}	/* Contact. */	if (param_contact) {	    contact = pjsip_contact_hdr_create(tdata->pool);	    pj_strdup_with_null(tdata->pool, &tmp, param_contact);	    contact->uri = pjsip_parse_uri( tdata->pool, tmp.ptr, tmp.slen,					    PJSIP_PARSE_URI_AS_NAMEADDR);	    if (contact->uri == NULL) {		status = PJSIP_EINVALIDHDR;		goto on_error;	    }	} else {	    contact = NULL;	}	/* Call-ID */	call_id = pjsip_cid_hdr_create(tdata->pool);	if (param_call_id != NULL && param_call_id->slen)	    pj_strdup(tdata->pool, &call_id->id, param_call_id);	else	    pj_create_unique_string(tdata->pool, &call_id->id);	/* CSeq */	cseq = pjsip_cseq_hdr_create(tdata->pool);	if (param_cseq >= 0)	    cseq->cseq = param_cseq;	else	    cseq->cseq = pj_rand() & 0xFFFF;	/* Method */	pjsip_method_copy(tdata->pool, &cseq->method, method);	/* Create the request. */	init_request_throw( endpt, tdata, &cseq->method, target, from, to,                             contact, call_id, cseq, param_text);    }    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;}PJ_DEF(pj_status_t)pjsip_endpt_create_request_from_hdr( pjsip_endpoint *endpt,				     const pjsip_method *method,				     const pjsip_uri *param_target,				     const pjsip_from_hdr *param_from,				     const pjsip_to_hdr *param_to,				     const pjsip_contact_hdr *param_contact,				     const pjsip_cid_hdr *param_call_id,				     int param_cseq,				     const pj_str_t *param_text,				     pjsip_tx_data **p_tdata){    pjsip_uri *target;    pjsip_tx_data *tdata;    pjsip_from_hdr *from;    pjsip_to_hdr *to;    pjsip_contact_hdr *contact;    pjsip_cid_hdr *call_id;    pjsip_cseq_hdr *cseq = NULL; /* The NULL because warning in VC6 */    pj_status_t status;    PJ_USE_EXCEPTION;    /* Check arguments. */    PJ_ASSERT_RETURN(endpt && method && param_target && param_from &&		     param_to && p_tdata, PJ_EINVAL);    /* Create new transmit data. */    status = pjsip_endpt_create_tdata(endpt, &tdata);    if (status != PJ_SUCCESS)	return status;    /* Set initial reference counter to 1. */    pjsip_tx_data_add_ref(tdata);    PJ_TRY {	/* Duplicate target URI and headers. */	target = pjsip_uri_clone(tdata->pool, param_target);	from = pjsip_hdr_clone(tdata->pool, param_from);	pjsip_fromto_hdr_set_from(from);	to = pjsip_hdr_clone(tdata->pool, param_to);	pjsip_fromto_hdr_set_to(to);	if (param_contact)	    contact = pjsip_hdr_clone(tdata->pool, param_contact);	else	    contact = NULL;	call_id = pjsip_hdr_clone(tdata->pool, param_call_id);	cseq = pjsip_cseq_hdr_create(tdata->pool);	if (param_cseq >= 0)	    cseq->cseq = param_cseq;	else	    cseq->cseq = pj_rand() % 0xFFFF;	pjsip_method_copy(tdata->pool, &cseq->method, method);	/* Copy headers to the request. */	init_request_throw(endpt, tdata, &cseq->method, target, from, to,                            contact, call_id, cseq, param_text);    }    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;}/* * Construct a minimal response message for the received request. */PJ_DEF(pj_status_t) pjsip_endpt_create_response( pjsip_endpoint *endpt,						 const pjsip_rx_data *rdata,						 int st_code,						 const pj_str_t *st_text,						 pjsip_tx_data **p_tdata){    pjsip_tx_data *tdata;    pjsip_msg *msg, *req_msg;    pjsip_hdr *hdr;    pjsip_via_hdr *via;    pjsip_rr_hdr *rr;    pj_status_t status;    /* Check arguments. */    PJ_ASSERT_RETURN(endpt && rdata && p_tdata, PJ_EINVAL);    /* Check status code. */    PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL);    /* rdata must be a request message. */    req_msg = rdata->msg_info.msg;    pj_assert(req_msg->type == PJSIP_REQUEST_MSG);    /* Request MUST NOT be ACK request! */    PJ_ASSERT_RETURN(req_msg->line.req.method.id != PJSIP_ACK_METHOD,		     PJ_EINVALIDOP);    /* Create a new transmit buffer. */    status = pjsip_endpt_create_tdata( endpt, &tdata);    if (status != PJ_SUCCESS)	return status;    /* Set initial reference count to 1. */    pjsip_tx_data_add_ref(tdata);    /* Create new response message. */    tdata->msg = msg = pjsip_msg_create(tdata->pool, PJSIP_RESPONSE_MSG);    /* Set status code and reason text. */    msg->line.status.code = st_code;    if (st_text)	pj_strdup(tdata->pool, &msg->line.status.reason, st_text);    else	msg->line.status.reason = *pjsip_get_status_text(st_code);    /* Set TX data attributes. */    tdata->rx_timestamp = rdata->pkt_info.timestamp;    /* Copy all the via headers, in order. */    via = rdata->msg_info.via;    while (via) {	pjsip_msg_add_hdr( msg, pjsip_hdr_clone(tdata->pool, via));	via = via->next;	if (via != (void*)&req_msg->hdr)	    via = pjsip_msg_find_hdr(req_msg, PJSIP_H_VIA, via);	else	    break;    }    /* Copy all Record-Route headers, in order. */    rr = pjsip_msg_find_hdr(req_msg, PJSIP_H_RECORD_ROUTE, NULL);    while (rr) {	pjsip_msg_add_hdr(msg, pjsip_hdr_clone(tdata->pool, rr));	rr = rr->next;	if (rr != (void*)&req_msg->hdr)	    rr = pjsip_msg_find_hdr(req_msg, PJSIP_H_RECORD_ROUTE, rr);	else	    break;    }    /* Copy Call-ID header. */    hdr = pjsip_msg_find_hdr( req_msg, PJSIP_H_CALL_ID, NULL);    pjsip_msg_add_hdr(msg, pjsip_hdr_clone(tdata->pool, hdr));    /* Copy From header. */    hdr = pjsip_hdr_clone(tdata->pool, rdata->msg_info.from);    pjsip_msg_add_hdr( msg, hdr);    /* Copy To header. */    hdr = pjsip_hdr_clone(tdata->pool, rdata->msg_info.to);    pjsip_msg_add_hdr( msg, hdr);    /* Copy CSeq header. */    hdr = pjsip_hdr_clone(tdata->pool, rdata->msg_info.cseq);    pjsip_msg_add_hdr( msg, hdr);    /* All done. */    *p_tdata = tdata;    PJ_LOG(5,(THIS_FILE, "%s created", pjsip_tx_data_get_info(tdata)));    return PJ_SUCCESS;}/* * Construct ACK for 3xx-6xx final response (according to chapter 17.1.1 of * RFC3261). Note that the generation of ACK for 2xx response is different, * and one must not use this function to generate such ACK. */PJ_DEF(pj_status_t) pjsip_endpt_create_ack( pjsip_endpoint *endpt,					    const pjsip_tx_data *tdata,					    const pjsip_rx_data *rdata,					    pjsip_tx_data **ack_tdata){    pjsip_tx_data *ack = NULL;    const pjsip_msg *invite_msg;    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;    pjsip_to_hdr *to;    pj_status_t status;    /* rdata must be a non-2xx final response. */

⌨️ 快捷键说明

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