📄 sip_msg.c
字号:
/* * $Id: sip_msg.c,v 1.84.2.2 2005/09/01 12:33:30 andrei Exp $ * * cloning a message into shared memory (TM keeps a snapshot * of messages in memory); note that many operations, which * allocate pkg memory (such as parsing) cannot be used with * a cloned message -- it would result in linking pkg structures * to shmem msg and eventually in a memory error * * the cloned message is stored in a single memory fragment to * save too many shm_mallocs -- these are expensive as they * not only take lookup in fragment table but also a shmem lock * operation (the same for shm_free) * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser 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 * * History: * -------- * 2003-01-23 - msg_cloner clones msg->from->parsed too (janakj) * 2003-01-29 - scratchpad removed (jiri) * 2003-02-25 - auth_body cloner added (janakj) * 2003-02-28 scratchpad compatibility abandoned (jiri) * 2003-03-31 removed msg->repl_add_rm (andrei) * 2003-04-04 parsed uris are recalculated on cloning (jiri) * 2003-05-07 received, rport & i via shortcuts are also translated (andrei) * 2003-11-11 updated cloning of lump_rpl (bogdan) * 2004-03-31 alias shortcuts are also translated (andrei) */#include "defs.h"#include <stdio.h>#include "sip_msg.h"#include "../../dprint.h"#include "../../mem/mem.h"#include "../../data_lump.h"#include "../../data_lump_rpl.h"#include "../../ut.h"#include "../../parser/digest/digest.h"/* rounds to the first 4 byte multiple on 32 bit archs * and to the first 8 byte multiple on 64 bit archs */#define ROUND4(s) \ (((s)+(sizeof(char*)-1))&(~(sizeof(char*)-1)))#define lump_len( _lump) \ (ROUND4(sizeof(struct lump)) +\ ROUND4(((_lump)->op==LUMP_ADD)?(_lump)->len:0))#define lump_clone( _new,_old,_ptr) \ {\ (_new) = (struct lump*)(_ptr);\ memcpy( (_new), (_old), sizeof(struct lump) );\ (_new)->flags|=LUMPFLAG_SHMEM; \ (_ptr)+=ROUND4(sizeof(struct lump));\ if ( (_old)->op==LUMP_ADD) {\ (_new)->u.value = (char*)(_ptr);\ memcpy( (_new)->u.value , (_old)->u.value , (_old)->len);\ (_ptr)+=ROUND4((_old)->len);}\ }inline struct via_body* via_body_cloner( char* new_buf, char *org_buf, struct via_body *param_org_via, char **p){ struct via_body *new_via; struct via_body *first_via, *last_via; struct via_body *org_via; first_via = last_via = 0; org_via = param_org_via; do { /* clones the via_body structure */ new_via = (struct via_body*)(*p); memcpy( new_via , org_via , sizeof( struct via_body) ); (*p) += ROUND4(sizeof( struct via_body )); /* hdr (str type) */ new_via->hdr.s=translate_pointer(new_buf,org_buf,org_via->hdr.s); /* name (str type) */ new_via->name.s=translate_pointer(new_buf,org_buf,org_via->name.s); /* version (str type) */ new_via->version.s= translate_pointer(new_buf,org_buf,org_via->version.s); /* transport (str type) */ new_via->transport.s= translate_pointer(new_buf,org_buf,org_via->transport.s); /* host (str type) */ new_via->host.s=translate_pointer(new_buf,org_buf,org_via->host.s); /* port_str (str type) */ new_via->port_str.s= translate_pointer(new_buf,org_buf,org_via->port_str.s); /* params (str type) */ new_via->params.s=translate_pointer(new_buf,org_buf,org_via->params.s); /* transaction id */ new_via->tid.s= translate_pointer(new_buf, org_buf, org_via->tid.s); /* comment (str type) */ new_via->comment.s= translate_pointer(new_buf,org_buf,org_via->comment.s); if ( org_via->param_lst ) { struct via_param *vp, *new_vp, *last_new_vp; for( vp=org_via->param_lst, last_new_vp=0 ; vp ; vp=vp->next ) { new_vp = (struct via_param*)(*p); memcpy( new_vp , vp , sizeof(struct via_param)); (*p) += ROUND4(sizeof(struct via_param)); new_vp->name.s=translate_pointer(new_buf,org_buf,vp->name.s); new_vp->value.s=translate_pointer(new_buf,org_buf,vp->value.s); new_vp->start=translate_pointer(new_buf,org_buf,vp->start); /* "translate" the shortcuts */ switch(new_vp->type){ case PARAM_BRANCH: new_via->branch = new_vp; break; case PARAM_RECEIVED: new_via->received = new_vp; break; case PARAM_RPORT: new_via->rport = new_vp; break; case PARAM_I: new_via->i = new_vp; break; case PARAM_ALIAS: new_via->alias = new_vp; break; } if (last_new_vp) last_new_vp->next = new_vp; else new_via->param_lst = new_vp; last_new_vp = new_vp; last_new_vp->next = NULL; } new_via->last_param = new_vp; }/*end if via has params */ if (last_via) last_via->next = new_via; else first_via = new_via; last_via = new_via; org_via = org_via->next; }while(org_via); return first_via;}static void uri_trans(char *new_buf, char *org_buf, struct sip_uri *uri){ uri->user.s=translate_pointer(new_buf,org_buf,uri->user.s); uri->passwd.s=translate_pointer(new_buf,org_buf,uri->passwd.s); uri->host.s=translate_pointer(new_buf,org_buf,uri->host.s); uri->port.s=translate_pointer(new_buf,org_buf,uri->port.s); uri->params.s=translate_pointer(new_buf,org_buf,uri->params.s); uri->headers.s=translate_pointer(new_buf,org_buf,uri->headers.s);}static inline struct auth_body* auth_body_cloner(char* new_buf, char *org_buf, struct auth_body *auth, char **p){ struct auth_body* new_auth; new_auth = (struct auth_body*)(*p); memcpy(new_auth , auth , sizeof(struct auth_body)); (*p) += ROUND4(sizeof(struct auth_body)); /* authorized field must be cloned elsewhere */ new_auth->digest.username.whole.s = translate_pointer(new_buf, org_buf, auth->digest.username.whole.s); new_auth->digest.username.user.s = translate_pointer(new_buf, org_buf, auth->digest.username.user.s); new_auth->digest.username.domain.s = translate_pointer(new_buf, org_buf, auth->digest.username.domain.s); new_auth->digest.realm.s = translate_pointer(new_buf, org_buf, auth->digest.realm.s); new_auth->digest.nonce.s = translate_pointer(new_buf, org_buf, auth->digest.nonce.s); new_auth->digest.uri.s = translate_pointer(new_buf, org_buf, auth->digest.uri.s); new_auth->digest.response.s = translate_pointer(new_buf, org_buf, auth->digest.response.s); new_auth->digest.alg.alg_str.s = translate_pointer(new_buf, org_buf, auth->digest.alg.alg_str.s); new_auth->digest.cnonce.s = translate_pointer(new_buf, org_buf, auth->digest.cnonce.s); new_auth->digest.opaque.s = translate_pointer(new_buf, org_buf, auth->digest.opaque.s); new_auth->digest.qop.qop_str.s = translate_pointer(new_buf, org_buf, auth->digest.qop.qop_str.s); new_auth->digest.nc.s = translate_pointer(new_buf, org_buf, auth->digest.nc.s); return new_auth;}static inline int clone_authorized_hooks(struct sip_msg* new, struct sip_msg* old){ struct hdr_field* ptr, *new_ptr, *hook1, *hook2; char stop = 0; get_authorized_cred(old->authorization, &hook1); if (!hook1) stop = 1; get_authorized_cred(old->proxy_auth, &hook2); if (!hook2) stop |= 2; ptr = old->headers; new_ptr = new->headers; while(ptr) { if (ptr == hook1) { if (!new->authorization || !new->authorization->parsed) { LOG(L_CRIT, "BUG: Error in message cloner (authorization)\n"); return -1; } ((struct auth_body*)new->authorization->parsed)->authorized = new_ptr; stop |= 1; } if (ptr == hook2) { if (!new->proxy_auth || !new->proxy_auth->parsed) { LOG(L_CRIT, "BUG: Error in message cloner (proxy_auth)\n"); return -1; } ((struct auth_body*)new->proxy_auth->parsed)->authorized = new_ptr; stop |= 2; } if (stop == 3) break; ptr = ptr->next; new_ptr = new_ptr->next; } return 0;}#define AUTH_BODY_SIZE sizeof(struct auth_body)#define HOOK_SET(hook) (new_msg->hook != org_msg->hook)struct sip_msg* sip_msg_cloner( struct sip_msg *org_msg, int *sip_msg_len ){ unsigned int len; struct hdr_field *hdr,*new_hdr,*last_hdr; struct via_body *via; struct via_param *prm; struct to_param *to_prm,*new_to_prm; struct sip_msg *new_msg; struct lump_rpl *rpl_lump, **rpl_lump_anchor; char *p; /*computing the length of entire sip_msg structure*/ len = ROUND4(sizeof( struct sip_msg )); /*we will keep only the original msg +ZT */ len += ROUND4(org_msg->len + 1); /*the new uri (if any)*/ if (org_msg->new_uri.s && org_msg->new_uri.len) len+= ROUND4(org_msg->new_uri.len); /*the dst uri (if any)*/ if (org_msg->dst_uri.s && org_msg->dst_uri.len) len+= ROUND4(org_msg->dst_uri.len); /*all the headers*/ for( hdr=org_msg->headers ; hdr ; hdr=hdr->next ) { /*size of header struct*/ len += ROUND4(sizeof( struct hdr_field)); switch (hdr->type) { case HDR_VIA: for (via=(struct via_body*)hdr->parsed;via;via=via->next) { len+=ROUND4(sizeof(struct via_body)); /*via param*/ for(prm=via->param_lst;prm;prm=prm->next) len+=ROUND4(sizeof(struct via_param )); } break; case HDR_TO: case HDR_FROM: /* From header might be unparsed */ if (hdr->parsed) { len+=ROUND4(sizeof(struct to_body)); /*to param*/ to_prm = ((struct to_body*)(hdr->parsed))->param_lst; for(;to_prm;to_prm=to_prm->next) len+=ROUND4(sizeof(struct to_param )); } break; case HDR_CSEQ: len+=ROUND4(sizeof(struct cseq_body)); break; case HDR_AUTHORIZATION: case HDR_PROXYAUTH: if (hdr->parsed) { len += ROUND4(AUTH_BODY_SIZE); } break; case HDR_CALLID: case HDR_CONTACT: case HDR_MAXFORWARDS: case HDR_ROUTE: case HDR_RECORDROUTE: case HDR_CONTENTTYPE: case HDR_CONTENTLENGTH: case HDR_EXPIRES: case HDR_SUPPORTED: case HDR_PROXYREQUIRE: case HDR_UNSUPPORTED: case HDR_ALLOW: case HDR_EVENT: case HDR_ACCEPT: case HDR_ACCEPTLANGUAGE: case HDR_ORGANIZATION: case HDR_PRIORITY: case HDR_SUBJECT: case HDR_USERAGENT: case HDR_ACCEPTDISPOSITION: case HDR_CONTENTDISPOSITION: /* we ignore them for now even if they have something parsed*/ break; default: if (hdr->parsed) { LOG(L_WARN, "WARNING: sip_msg_cloner: " "header body ignored: %d\n", hdr->type ); } break; }/*switch*/ }/*for all headers*/ /* length of the data lump structures */#define LUMP_LIST_LEN(len, list) \do { \ struct lump* tmp, *chain; \ chain = (list); \ while (chain) \ { \ (len) += lump_len(chain); \ tmp = chain->before; \ while ( tmp ) \ { \ (len) += lump_len( tmp ); \ tmp = tmp->before; \ } \ tmp = chain->after; \ while ( tmp ) \ { \ (len) += lump_len( tmp ); \ tmp = tmp->after; \ } \ chain = chain->next; \ } \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -