uac_unixsock.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 624 行 · 第 1/2 页

C
624
字号
/* * $Id: uac_unixsock.c,v 1.4 2006/04/05 08:47:38 bogdan_iancu Exp $ * * Copyright (C) 2001-2004 FhG Fokus * * This file is part of openser, a free SIP server. * * openser 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 * * openser 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 <string.h>#include "../../mem/mem.h"#include "../../mem/shm_mem.h"#include "../../parser/hf.h"#include "../../dprint.h"#include "../../parser/parse_uri.h"#include "../../unixsock_server.h"#include "../../parser/msg_parser.h"#include "../../parser/parse_to.h"#include "../../parser/parse_cseq.h"#include "../../parser/parse_from.h"#include "../../ut.h"#include "uac_unixsock.h"#include "config.h"#include "ut.h"#include "t_hooks.h"#include "callid.h"#include "uac.h"#include "dlg.h"struct str_list {	str s;	struct str_list *next;};struct uac_cb_param {    str from;    str callid;    str cseq;    struct sockaddr_un addr;};#define skip_hf(_hf) (               \    ((_hf)->type == HDR_FROM_T)   || \    ((_hf)->type == HDR_TO_T)     || \    ((_hf)->type == HDR_CALLID_T) || \    ((_hf)->type == HDR_CSEQ_T)      \)/* * Read the method from the request */static int get_method(str* method, str* msg){	if (unixsock_read_line(method, msg) != 0) {		unixsock_reply_asciiz("400 Method expected");		unixsock_reply_send();		return -1;	}	DBG("get_method: method: '%.*s'\n", method->len, ZSW(method->s));	return 0;}/* * Read the Request-URI and parse it */static int get_ruri(str* ruri, struct sip_uri* puri, str* msg){	if (unixsock_read_line(ruri, msg) != 0) {		unixsock_reply_asciiz("400 Request-URI expected");		unixsock_reply_send();		return -1;	}		if (parse_uri(ruri->s, ruri->len, puri) < 0 ) {		unixsock_reply_asciiz("400 Request-URI is invalid\n");		unixsock_reply_send();		return -1;	}	DBG("get_ruri: '%.*s'\n", ruri->len, ZSW(ruri->s));	return 0;}/* * Read and parse the next hop */static int get_nexthop(str* nexthop, struct sip_uri* pnexthop, str* msg){	if (unixsock_read_line(nexthop, msg) != 0) {		unixsock_reply_asciiz("400 Next-hop URI expected\n");		unixsock_reply_send();		return -1;	}	if (nexthop->len == 1 && nexthop->s[0] == '.' ) {		DBG("get_nexthop: next hop empty\n");		nexthop->s = 0; 		nexthop->len = 0;	} else if (parse_uri(nexthop->s, nexthop->len, pnexthop) < 0 ) {		unixsock_reply_asciiz("400 Next-hop URI is invalid\n");		unixsock_reply_send();		return -1;	} else {		DBG("get_nexthop: '%.*s'\n", nexthop->len, ZSW(nexthop->s));	}	return 0;}/* * Read header into a static buffer (it is necessary because * the unixsock_read_lineset performs CRLF recovery and thus * the result may be longer than the original */static int get_headers(str* headers, str* msg){	static char headers_buf[MAX_HEADER];	headers->s = headers_buf;	headers->len = MAX_HEADER;	     /* now read and parse header fields */	if (unixsock_read_lineset(headers, msg) < 0) {		unixsock_reply_asciiz("400 Header fields expected\n");		unixsock_reply_send();		return -1;	}	DBG("get_headers: %.*s\n", headers->len, ZSW(headers->s));	return 0;}/* * Read the message body */static int get_body_lines(str* body, str* msg){	if (unixsock_read_body(body, msg) < 0) {		unixsock_reply_asciiz("400 Body expected\n");		unixsock_reply_send();		return -1;	}	DBG("get_body_lines: %.*s\n", body->len,  ZSW(body->s));	return 0;}/* * Make sure that the FIFO user created the message * correctly */static int check_msg(struct sip_msg* msg, str* method, str* body, 		     int* fromtag, int *cseq_is, int* cseq, str* callid){	struct to_body* parsed_from;	struct cseq_body *parsed_cseq;	int i;	char c;	if (body->len && !msg->content_type) {		unixsock_reply_asciiz("400 Content-Type missing");		goto err;	}	if (body->len && msg->content_length) {		unixsock_reply_asciiz("400 Content-Length disallowed");		goto err;	}	if (!msg->to) {		unixsock_reply_asciiz("400 To missing");		goto err;	}	if (!msg->from) {		unixsock_reply_asciiz("400 From missing");		goto err;	}	     /* we also need to know if there is from-tag and add it otherwise */	if (parse_from_header(msg) < 0) {		unixsock_reply_asciiz("400 Error in From");		goto err;	}	parsed_from = (struct to_body*)msg->from->parsed;	*fromtag = parsed_from->tag_value.s && parsed_from->tag_value.len;	*cseq = 0;	if (msg->cseq && (parsed_cseq = get_cseq(msg))) {		*cseq_is = 1;		for (i = 0; i < parsed_cseq->number.len; i++) {			c = parsed_cseq->number.s[i];			if (c >= '0' && c <= '9' ) {				*cseq = (*cseq) * 10 + c - '0';			} else {			        DBG("check_msg: Found non-numerical in CSeq: <%i>='%c'\n", (unsigned int)c, c);				unixsock_reply_asciiz("400 Non-numerical CSeq");				goto err;			}		}				if (parsed_cseq->method.len != method->len 		    || memcmp(parsed_cseq->method.s, method->s, method->len) !=0 ) {			unixsock_reply_asciiz("400 CSeq method mismatch");			goto err;		}	} else {		*cseq_is = 0;	}	if (msg->callid) {		callid->s = msg->callid->body.s;		callid->len = msg->callid->body.len;	} else {		callid->s = 0;		callid->len = 0;	}	return 0; err:	unixsock_reply_send();	return -1;}static inline struct str_list *new_str(char *s, int len, struct str_list **last, int *total){	struct str_list *new;	new = pkg_malloc(sizeof(struct str_list));	if (!new) {		LOG(L_ERR, "new_str: Not enough mem\n");		return 0;	}	new->s.s = s;	new->s.len = len;	new->next = 0;	(*last)->next = new;	*last = new;	*total += len;	return new;}static char *get_hfblock(str *uri, struct hdr_field *hf, int *l, int proto) {	struct str_list sl, *last, *i, *foo;	int p, frag_len, total_len;	char *begin, *needle, *dst, *ret, *d;	str *sock_name, *portname;	union sockaddr_union to_su;	struct socket_info* send_sock;	ret = 0; /* pessimist: assume failure */	total_len = 0;	last = &sl;	last->next = 0;	portname = sock_name = 0;	for (; hf; hf = hf->next) {		if (skip_hf(hf)) continue;		begin = needle = hf->name.s; 		p = hf->len;		     /* substitution loop */		while(p) {			d = q_memchr(needle, SUBST_CHAR, p);			if (!d || d + 1 >= needle + p) { /* nothing to substitute */				if (!new_str(begin, p, &last, &total_len)) goto error;				break;			} else {				frag_len = d - begin;				d++; /* d not at the second substitution char */				switch(*d) {				case SUBST_CHAR: /* double SUBST_CHAR: IP */					     /* string before substitute */					if (!new_str(begin, frag_len, &last, &total_len)) goto error;					     /* substitute */					if (!sock_name) {						send_sock = uri2sock(0, uri, &to_su, proto);						if (!send_sock) {							LOG(L_ERR, "ERROR: get_hfblock: send_sock failed\n");							goto error;						}						sock_name = &send_sock->address_str;						portname = &send_sock->port_no_str;					}					if (!new_str(sock_name->s, sock_name->len, &last, &total_len)) goto error;					     /* inefficient - FIXME --andrei*/					if (!new_str(":", 1, &last, &total_len)) goto error;					if (!new_str(portname->s, portname->len, &last, &total_len)) goto error;					     /* keep going ... */					begin = needle = d + 1;					p -= frag_len + 2;

⌨️ 快捷键说明

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