📄 t_msgbuilder.c
字号:
/* * $Id: t_msgbuilder.c,v 1.40 2004/11/09 15:15:12 andrei Exp $ * * message printing * * 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-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) * 2003-02-13 build_uac_request uses proto (andrei) * 2003-02-28 scratchpad compatibility abandoned (jiri) * 2003-04-14 build_local no longer checks reply status as it * is now called before reply status is updated to * avoid late ACK sending (jiri) * 2003-10-02 added via_builder set host/port support (andrei) * 2004-02-11 FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri) * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan) */#include "defs.h"#include "../../comp_defs.h"#include "../../hash_func.h"#include "../../globals.h"#include "t_funcs.h"#include "../../dprint.h"#include "../../config.h"#include "../../parser/parser_f.h"#include "../../ut.h"#include "../../parser/msg_parser.h"#include "../../parser/contact/parse_contact.h"#include "t_msgbuilder.h"#include "uac.h"#define ROUTE_PREFIX "Route: "#define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX) - 1)#define ROUTE_SEPARATOR ", "#define ROUTE_SEPARATOR_LEN (sizeof(ROUTE_SEPARATOR) - 1)#define append_mem_block(_d,_s,_len) \ do{\ memcpy((_d),(_s),(_len));\ (_d) += (_len);\ }while(0);#define append_str(_p,_str) \ do{ \ memcpy((_p), (_str).s, (_str).len); \ (_p)+=(_str).len; \ } while(0);/* Build a local request based on a previous request; main customers of this function are local ACK and local CANCEL */char *build_local(struct cell *Trans,unsigned int branch, unsigned int *len, char *method, int method_len, str *to){ char *cancel_buf, *p, *via; unsigned int via_len; struct hdr_field *hdr; char branch_buf[MAX_BRANCH_PARAM_LEN]; int branch_len; str branch_str; struct hostport hp;#ifdef _OBSO if ( Trans->uac[branch].last_received<100) { DBG("DEBUG: build_local: no response ever received" " : dropping local request! \n"); goto error; }#endif /* method, separators, version: "CANCEL sip:p2@iptel.org SIP/2.0" */ *len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN; *len+=Trans->uac[branch].uri.len; /*via*/ if (!t_calc_branch(Trans, branch, branch_buf, &branch_len )) goto error; branch_str.s=branch_buf; branch_str.len=branch_len; set_hostport(&hp, (is_local(Trans))?0:(Trans->uas.request)); via=via_builder(&via_len, Trans->uac[branch].request.dst.send_sock, &branch_str, 0, Trans->uac[branch].request.dst.proto, &hp ); if (!via) { LOG(L_ERR, "ERROR: build_local: " "no via header got from builder\n"); goto error; } *len+= via_len; /*headers*/ *len+=Trans->from.len+Trans->callid.len+to->len+ +Trans->cseq_n.len+1+method_len+CRLF_LEN; /* copy'n'paste Route headers */ if (!is_local(Trans)) { for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next ) if (hdr->type==HDR_ROUTE) *len+=hdr->len; } /* User Agent */ if (server_signature) { *len += USER_AGENT_LEN + CRLF_LEN; } /* Content Length, EoM */ *len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN; cancel_buf=shm_malloc( *len+1 ); if (!cancel_buf) { LOG(L_ERR, "ERROR: build_local: cannot allocate memory\n"); goto error01; } p = cancel_buf; append_mem_block( p, method, method_len ); append_mem_block( p, " ", 1 ); append_str( p, Trans->uac[branch].uri ); append_mem_block( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN ); /* insert our via */ append_mem_block(p,via,via_len); /*other headers*/ append_str( p, Trans->from ); append_str( p, Trans->callid ); append_str( p, *to ); append_str( p, Trans->cseq_n ); append_mem_block( p, " ", 1 ); append_mem_block( p, method, method_len ); append_mem_block( p, CRLF, CRLF_LEN ); if (!is_local(Trans)) { for ( hdr=Trans->uas.request->headers ; hdr ; hdr=hdr->next ) if(hdr->type==HDR_ROUTE) { append_mem_block(p, hdr->name.s, hdr->len ); } } /* User Agent header */ if (server_signature) { append_mem_block(p,USER_AGENT CRLF, USER_AGENT_LEN+CRLF_LEN ); } /* Content Length, EoM */ append_mem_block(p, CONTENT_LENGTH "0" CRLF CRLF , CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN); *p=0; pkg_free(via); return cancel_buf;error01: pkg_free(via);error: return NULL;}struct rte { rr_t* ptr; struct rte* next;}; static inline void free_rte_list(struct rte* list){ struct rte* ptr; while(list) { ptr = list; list = list->next; pkg_free(ptr); }}static inline int process_routeset(struct sip_msg* msg, str* contact, struct rte** list, str* ruri, str* next_hop){ struct hdr_field* ptr; rr_t* p; struct rte* t, *head; struct sip_uri puri; ptr = msg->record_route; head = 0; while(ptr) { if (ptr->type == HDR_RECORDROUTE) { if (parse_rr(ptr) < 0) { LOG(L_ERR, "process_routeset: Error while parsing Record-Route header\n"); return -1; } p = (rr_t*)ptr->parsed; while(p) { t = (struct rte*)pkg_malloc(sizeof(struct rte)); if (!t) { LOG(L_ERR, "process_routeset: No memory left\n"); free_rte_list(head); return -1; } t->ptr = p; t->next = head; head = t; p = p->next; } } ptr = ptr->next; } if (head) { if (parse_uri(head->ptr->nameaddr.uri.s, head->ptr->nameaddr.uri.len, &puri) == -1) { LOG(L_ERR, "process_routeset: Error while parsing URI\n"); free_rte_list(head); return -1; } if (puri.lr.s) { /* Next hop is loose router */ *ruri = *contact; *next_hop = head->ptr->nameaddr.uri; } else { /* Next hop is strict router */ *ruri = head->ptr->nameaddr.uri; *next_hop = *ruri; t = head; head = head->next; pkg_free(t); } } else { /* No routes */ *ruri = *contact; *next_hop = *contact; } *list = head; return 0;}static inline int calc_routeset_len(struct rte* list, str* contact){ struct rte* ptr; int ret; if (list || contact) { ret = ROUTE_PREFIX_LEN + CRLF_LEN; } else { return 0; } ptr = list; while(ptr) { if (ptr != list) { ret += ROUTE_SEPARATOR_LEN; } ret += ptr->ptr->len; ptr = ptr->next; } if (contact) { if (list) ret += ROUTE_SEPARATOR_LEN; ret += 2 + contact->len; } return ret;} /* * Print the route set */static inline char* print_rs(char* p, struct rte* list, str* contact){ struct rte* ptr; if (list || contact) { memapp(p, ROUTE_PREFIX, ROUTE_PREFIX_LEN); } else { return p; } ptr = list; while(ptr) { if (ptr != list) { memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN); } memapp(p, ptr->ptr->nameaddr.name.s, ptr->ptr->len); ptr = ptr->next; } if (contact) { if (list) memapp(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN); *p++ = '<'; append_str(p, *contact); *p++ = '>'; } memapp(p, CRLF, CRLF_LEN); return p;} /* * Parse Contact header field body and extract URI * Does not parse headers ! */static inline int get_contact_uri(struct sip_msg* msg, str* uri){ contact_t* c; uri->len = 0; if (!msg->contact) return 1; if (parse_contact(msg->contact) < 0) { LOG(L_ERR, "get_contact_uri: Error while parsing Contact body\n"); return -1; } c = ((contact_body_t*)msg->contact->parsed)->contacts; if (!c) { LOG(L_ERR, "get_contact_uri: Empty body or * contact\n"); return -2; } *uri = c->uri; return 0;} /* * The function creates an ACK to 200 OK. Route set will be created * and parsed and next_hop parameter will contain uri the which the * request should be send. The function is used by tm when it generates * local ACK to 200 OK (on behalf of applications using uac */char *build_dlg_ack(struct sip_msg* rpl, struct cell *Trans, unsigned int branch, str* to, unsigned int *len, str *next_hop){ char *req_buf, *p, *via; unsigned int via_len; char branch_buf[MAX_BRANCH_PARAM_LEN]; int branch_len; str branch_str; struct hostport hp; struct rte* list; str contact, ruri, *cont; struct socket_info* send_sock; union sockaddr_union to_su; if (get_contact_uri(rpl, &contact) < 0) { return 0; } if (process_routeset(rpl, &contact, &list, &ruri, next_hop) < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -