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 + -
显示快捷键?