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

📄 sip_msg.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: sip_msg.c 1219 2007-04-28 15:35:01Z 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_msg.h>#include <pjsip/sip_parser.h>#include <pjsip/print_util.h>#include <pjsip/sip_errno.h>#include <pj/string.h>#include <pj/pool.h>#include <pj/assert.h>const pjsip_method     pjsip_invite_method	    = { PJSIP_INVITE_METHOD,	{ "INVITE",6 }	},    pjsip_cancel_method	    = { PJSIP_CANCEL_METHOD,	{ "CANCEL",6 }	},    pjsip_ack_method	    = { PJSIP_ACK_METHOD,	{ "ACK",3}	},    pjsip_bye_method	    = { PJSIP_BYE_METHOD,	{ "BYE",3}	},    pjsip_register_method   = { PJSIP_REGISTER_METHOD,	{ "REGISTER",8}	},    pjsip_options_method    = { PJSIP_OPTIONS_METHOD,	{ "OPTIONS",7}	};static const pj_str_t *method_names[] = {    &pjsip_invite_method.name,    &pjsip_cancel_method.name,    &pjsip_ack_method.name,    &pjsip_bye_method.name,    &pjsip_register_method.name,    &pjsip_options_method.name};const pj_str_t pjsip_hdr_names[] = {    { "Accept",		     6 },   // PJSIP_H_ACCEPT,    { "Accept-Encoding",    15 },   // PJSIP_H_ACCEPT_ENCODING,    { "Accept-Language",    15 },   // PJSIP_H_ACCEPT_LANGUAGE,    { "Alert-Info",	    10 },   // PJSIP_H_ALERT_INFO,    { "Allow",		     5 },   // PJSIP_H_ALLOW,    { "Authentication-Info",19 },   // PJSIP_H_AUTHENTICATION_INFO,    { "Authorization",	    13 },   // PJSIP_H_AUTHORIZATION,    { "Call-ID",	     7 },   // PJSIP_H_CALL_ID,    { "Call-Info",	     9 },   // PJSIP_H_CALL_INFO,    { "Contact",	     7 },   // PJSIP_H_CONTACT,    { "Content-Disposition",19 },   // PJSIP_H_CONTENT_DISPOSITION,    { "Content-Encoding",   16 },   // PJSIP_H_CONTENT_ENCODING,    { "Content-Language",   16 },   // PJSIP_H_CONTENT_LANGUAGE,    { "Content-Length",	    14 },   // PJSIP_H_CONTENT_LENGTH,    { "Content-Type",	    12 },   // PJSIP_H_CONTENT_TYPE,    { "CSeq",		     4 },   // PJSIP_H_CSEQ,    { "Date",		     4 },   // PJSIP_H_DATE,    { "Error-Info",	    10 },   // PJSIP_H_ERROR_INFO,    { "Expires",	     7 },   // PJSIP_H_EXPIRES,    { "From",		     4 },   // PJSIP_H_FROM,    { "In-Reply-To",	    11 },   // PJSIP_H_IN_REPLY_TO,    { "Max-Forwards",	    12 },   // PJSIP_H_MAX_FORWARDS,    { "MIME-Version",	    12 },   // PJSIP_H_MIME_VERSION,    { "Min-Expires",	    11 },   // PJSIP_H_MIN_EXPIRES,    { "Organization",	    12 },   // PJSIP_H_ORGANIZATION,    { "Priority",	     8 },   // PJSIP_H_PRIORITY,    { "Proxy-Authenticate", 18 },   // PJSIP_H_PROXY_AUTHENTICATE,    { "Proxy-Authorization",19 },   // PJSIP_H_PROXY_AUTHORIZATION,    { "Proxy-Require",	    13 },   // PJSIP_H_PROXY_REQUIRE,    { "Record-Route",	    12 },   // PJSIP_H_RECORD_ROUTE,    { "Reply-To",	     8 },   // PJSIP_H_REPLY_TO,    { "Require",	     7 },   // PJSIP_H_REQUIRE,    { "Retry-After",	    11 },   // PJSIP_H_RETRY_AFTER,    { "Route",		     5 },   // PJSIP_H_ROUTE,    { "Server",		     6 },   // PJSIP_H_SERVER,    { "Subject",	     7 },   // PJSIP_H_SUBJECT,    { "Supported",	     9 },   // PJSIP_H_SUPPORTED,    { "Timestamp",	     9 },   // PJSIP_H_TIMESTAMP,    { "To",		     2 },   // PJSIP_H_TO,    { "Unsupported",	    11 },   // PJSIP_H_UNSUPPORTED,    { "User-Agent",	    10 },   // PJSIP_H_USER_AGENT,    { "Via",		     3 },   // PJSIP_H_VIA,    { "Warning",	     7 },   // PJSIP_H_WARNING,    { "WWW-Authenticate",   16 },   // PJSIP_H_WWW_AUTHENTICATE,    { "_Unknown-Header",    15 },   // PJSIP_H_OTHER,};static pj_str_t status_phrase[710];static int print_media_type(char *buf, const pjsip_media_type *media);static int init_status_phrase(){    int i;    pj_str_t default_reason_phrase = { "Default status message", 22};    for (i=0; i<PJ_ARRAY_SIZE(status_phrase); ++i)	status_phrase[i] = default_reason_phrase;    pj_strset2( &status_phrase[100], "Trying");    pj_strset2( &status_phrase[180], "Ringing");    pj_strset2( &status_phrase[181], "Call Is Being Forwarded");    pj_strset2( &status_phrase[182], "Queued");    pj_strset2( &status_phrase[183], "Session Progress");    pj_strset2( &status_phrase[200], "OK");    pj_strset2( &status_phrase[202], "Accepted");    pj_strset2( &status_phrase[300], "Multiple Choices");    pj_strset2( &status_phrase[301], "Moved Permanently");    pj_strset2( &status_phrase[302], "Moved Temporarily");    pj_strset2( &status_phrase[305], "Use Proxy");    pj_strset2( &status_phrase[380], "Alternative Service");    pj_strset2( &status_phrase[400], "Bad Request");    pj_strset2( &status_phrase[401], "Unauthorized");    pj_strset2( &status_phrase[402], "Payment Required");    pj_strset2( &status_phrase[403], "Forbidden");    pj_strset2( &status_phrase[404], "Not Found");    pj_strset2( &status_phrase[405], "Method Not Allowed");    pj_strset2( &status_phrase[406], "Not Acceptable");    pj_strset2( &status_phrase[407], "Proxy Authentication Required");    pj_strset2( &status_phrase[408], "Request Timeout");    pj_strset2( &status_phrase[410], "Gone");    pj_strset2( &status_phrase[413], "Request Entity Too Large");    pj_strset2( &status_phrase[414], "Request URI Too Long");    pj_strset2( &status_phrase[415], "Unsupported Media Type");    pj_strset2( &status_phrase[416], "Unsupported URI Scheme");    pj_strset2( &status_phrase[420], "Bad Extension");    pj_strset2( &status_phrase[421], "Extension Required");    pj_strset2( &status_phrase[422], "Session Timer Too Small");    pj_strset2( &status_phrase[423], "Interval Too Brief");    pj_strset2( &status_phrase[480], "Temporarily Unavailable");    pj_strset2( &status_phrase[481], "Call/Transaction Does Not Exist");    pj_strset2( &status_phrase[482], "Loop Detected");    pj_strset2( &status_phrase[483], "Too Many Hops");    pj_strset2( &status_phrase[484], "Address Incompleted");    pj_strset2( &status_phrase[485], "Ambiguous");    pj_strset2( &status_phrase[486], "Busy Here");    pj_strset2( &status_phrase[487], "Request Terminated");    pj_strset2( &status_phrase[488], "Not Acceptable Here");    pj_strset2( &status_phrase[489], "Bad Event");    pj_strset2( &status_phrase[490], "Request Updated");    pj_strset2( &status_phrase[491], "Request Pending");    pj_strset2( &status_phrase[493], "Undecipherable");    pj_strset2( &status_phrase[500], "Internal Server Error");    pj_strset2( &status_phrase[501], "Not Implemented");    pj_strset2( &status_phrase[502], "Bad Gateway");    pj_strset2( &status_phrase[503], "Service Unavailable");    pj_strset2( &status_phrase[504], "Server Timeout");    pj_strset2( &status_phrase[505], "Version Not Supported");    pj_strset2( &status_phrase[513], "Message Too Large");    pj_strset2( &status_phrase[580], "Precondition Failure");    pj_strset2( &status_phrase[600], "Busy Everywhere");    pj_strset2( &status_phrase[603], "Decline");    pj_strset2( &status_phrase[604], "Does Not Exist Anywhere");    pj_strset2( &status_phrase[606], "Not Acceptable");    pj_strset2( &status_phrase[701], "No response from destination server");    pj_strset2( &status_phrase[702], "Unable to resolve destination server");    pj_strset2( &status_phrase[703], "Error sending message to destination server");    return 1;}////////////////////////////////////////////////////////////////////////////////* * Method. */PJ_DEF(void) pjsip_method_init( pjsip_method *m, 			        pj_pool_t *pool, 			        const pj_str_t *str){    pj_str_t dup;    pjsip_method_init_np(m, pj_strdup(pool, &dup, str));}PJ_DEF(void) pjsip_method_set( pjsip_method *m, pjsip_method_e me ){    pj_assert(me < PJSIP_OTHER_METHOD);    m->id = me;    m->name = *method_names[me];}PJ_DEF(void) pjsip_method_init_np(pjsip_method *m,				  pj_str_t *str){    int i;    for (i=0; i<PJ_ARRAY_SIZE(method_names); ++i) {	if (pj_memcmp(str->ptr, method_names[i]->ptr, str->slen)==0 || 	    pj_stricmp(str, method_names[i])==0) 	{	    m->id = (pjsip_method_e)i;	    m->name = *method_names[i];	    return;	}    }    m->id = PJSIP_OTHER_METHOD;    m->name = *str;}PJ_DEF(void) pjsip_method_copy( pj_pool_t *pool,				pjsip_method *method,				const pjsip_method *rhs ){    method->id = rhs->id;    if (rhs->id != PJSIP_OTHER_METHOD) {	method->name = rhs->name;    } else {	pj_strdup(pool, &method->name, &rhs->name);    }}PJ_DEF(int) pjsip_method_cmp( const pjsip_method *m1, const pjsip_method *m2){    if (m1->id == m2->id) {	if (m1->id != PJSIP_OTHER_METHOD)	    return 0;	/* Method comparison is case sensitive! */	return pj_strcmp(&m1->name, &m2->name);    }        return ( m1->id < m2->id ) ? -1 : 1;}////////////////////////////////////////////////////////////////////////////////* * Message. */PJ_DEF(pjsip_msg*) pjsip_msg_create( pj_pool_t *pool, pjsip_msg_type_e type){    pjsip_msg *msg = pj_pool_alloc(pool, sizeof(pjsip_msg));    pj_list_init(&msg->hdr);    msg->type = type;    msg->body = NULL;    return msg;}PJ_DEF(pjsip_msg*) pjsip_msg_clone( pj_pool_t *pool, const pjsip_msg *src){    pjsip_msg *dst;    const pjsip_hdr *sh;    dst = pjsip_msg_create(pool, src->type);    /* Clone request/status line */    if (src->type == PJSIP_REQUEST_MSG) {	pjsip_method_copy(pool, &dst->line.req.method, &src->line.req.method);	dst->line.req.uri = pjsip_uri_clone(pool, src->line.req.uri);    } else {	dst->line.status.code = src->line.status.code;	pj_strdup(pool, &dst->line.status.reason, &src->line.status.reason);    }    /* Clone headers */    sh = src->hdr.next;    while (sh != &src->hdr) {	pjsip_hdr *dh = pjsip_hdr_clone(pool, sh);	pjsip_msg_add_hdr(dst, dh);	sh = sh->next;    }    /* Clone message body */    if (src->body) {	dst->body = pjsip_msg_body_clone(pool, src->body);    }    return dst;}PJ_DEF(void*)  pjsip_msg_find_hdr( const pjsip_msg *msg, 				   pjsip_hdr_e hdr_type, const void *start){    const pjsip_hdr *hdr=start, *end=&msg->hdr;    if (hdr == NULL) {	hdr = msg->hdr.next;    }    for (; hdr!=end; hdr = hdr->next) {	if (hdr->type == hdr_type)	    return (void*)hdr;    }    return NULL;}PJ_DEF(void*)  pjsip_msg_find_hdr_by_name( const pjsip_msg *msg, 					   const pj_str_t *name, 					   const void *start){    const pjsip_hdr *hdr=start, *end=&msg->hdr;    if (hdr == NULL) {	hdr = msg->hdr.next;    }    for (; hdr!=end; hdr = hdr->next) {	if (hdr->type < PJSIP_H_OTHER) {	    if (pj_stricmp(&pjsip_hdr_names[hdr->type], name) == 0)		return (void*)hdr;	} else {	    if (pj_stricmp(&hdr->name, name) == 0)		return (void*)hdr;	}    }    return NULL;}PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg, 				         pjsip_hdr_e hdr_type, void *start){    pjsip_hdr *hdr = pjsip_msg_find_hdr(msg, hdr_type, start);    if (hdr) {	pj_list_erase(hdr);    }    return hdr;}PJ_DEF(pj_ssize_t) pjsip_msg_print( const pjsip_msg *msg, 				    char *buf, pj_size_t size){    char *p=buf, *end=buf+size;    int len;    pjsip_hdr *hdr;    pj_str_t clen_hdr =  { "Content-Length: ", 16};    /* Get a wild guess on how many bytes are typically needed.     * We'll check this later in detail, but this serves as a quick check.     */    if (size < 256)	return -1;    /* Print request line or status line depending on message type */    if (msg->type == PJSIP_REQUEST_MSG) {	pjsip_uri *uri;	/* Add method. */	len = msg->line.req.method.name.slen;	pj_memcpy(p, msg->line.req.method.name.ptr, len);	p += len;	*p++ = ' ';	/* Add URI */	uri = pjsip_uri_get_uri(msg->line.req.uri);	len = pjsip_uri_print( PJSIP_URI_IN_REQ_URI, uri, p, end-p);	if (len < 1)	    return -1;	p += len;	/* Add ' SIP/2.0' */	if (end-p < 16)	    return -1;	pj_memcpy(p, " SIP/2.0\r\n", 10);	p += 10;    } else {	/* Add 'SIP/2.0 ' */	pj_memcpy(p, "SIP/2.0 ", 8);	p += 8;	/* Add status code. */	len = pj_utoa(msg->line.status.code, p);	p += len;	*p++ = ' ';	/* Add reason text. */	len = msg->line.status.reason.slen;	pj_memcpy(p, msg->line.status.reason.ptr, len );	p += len;	/* Add newline. */	*p++ = '\r';	*p++ = '\n';    }    /* Print each of the headers. */    for (hdr=msg->hdr.next; hdr!=&msg->hdr; hdr=hdr->next) {	len = (*hdr->vptr->print_on)(hdr, p, end-p);	if (len < 1)	    return -1;	p += len;	if (p+3 >= end)	    return -1;	*p++ = '\r';	*p++ = '\n';    }    /* Process message body. */    if (msg->body) {	enum { CLEN_SPACE = 5 };	char *clen_pos = NULL;	/* Automaticly adds Content-Type and Content-Length headers, only	 * if content_type is set in the message body.	 */	if (msg->body->content_type.type.slen) {	    pj_str_t ctype_hdr = { "Content-Type: ", 14};	    const pjsip_media_type *media = &msg->body->content_type;	    /* Add Content-Type header. */	    if ( (end-p) < 24 + media->type.slen + media->subtype.slen + 			   media->param.slen) 	    {		return -1;	    }	    pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen);	    p += ctype_hdr.slen;	    p += print_media_type(p, media);	    *p++ = '\r';	    *p++ = '\n';	    /* Add Content-Length header. */	    if ((end-p) < clen_hdr.slen + 12 + 2) {		return -1;	    }	    pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);	    p += clen_hdr.slen;	    	    /* Print blanks after "Content-Length:", this is where we'll put	     * the content length value after we know the length of the	     * body.	     */	    pj_memset(p, ' ', CLEN_SPACE);	    clen_pos = p;	    p += CLEN_SPACE;	    *p++ = '\r';	    *p++ = '\n';	}		/* Add blank newline. */	*p++ = '\r';	*p++ = '\n';	/* Print the message body itself. */	len = (*msg->body->print_body)(msg->body, p, end-p);	if (len < 0) {	    return -1;	}	p += len;	/* Now that we have the length of the body, print this to the	 * Content-Length header.	 */	if (clen_pos) {	    char tmp[16];	    len = pj_utoa(len, tmp);	    if (len > CLEN_SPACE) len = CLEN_SPACE;	    pj_memcpy(clen_pos+CLEN_SPACE-len, tmp, len);	}    } else {	/* There's no message body.	 * Add Content-Length with zero value.	 */	if ((end-p) < clen_hdr.slen+8) {	    return -1;	}	pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);	p += clen_hdr.slen;	*p++ = ' ';	*p++ = '0';	*p++ = '\r';

⌨️ 快捷键说明

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