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

📄 uac.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/* * $Id: uac.c,v 1.52 2004/11/09 15:15:12 andrei Exp $ * * simple UAC for things such as SUBSCRIBE or SMS gateway; * no authentication and other UAC features -- just send * a message, retransmit and await a reply; forking is not * supported during client generation, in all other places * it is -- adding it should be simple * * 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  t_uac_dlg now uses get_out_socket (jiri) *  2003-01-27  fifo:t_uac_dlg completed (jiri) *  2003-01-29  scratchpad removed (jiri) *  2003-02-13  t_uac, t _uac_dlg, gethfblock, uri2proxy changed to use  *               proto & rb->dst (andrei) *  2003-02-27  FIFO/UAC now dumps reply -- good for CTD (jiri) *  2003-02-28  scratchpad compatibility abandoned (jiri) *  2003-03-01  kr set through a function now (jiri) *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei) *  2003-04-02  port_no_str does not contain a leading ':' anymore (andrei) *  2003-07-08  appropriate log messages in check_params(...),  *               call calculate_hooks if next_hop==NULL in t_uac (dcm)  *  2003-10-24  updated to the new socket_info lists (andrei) *  2003-12-03  completion filed removed from transaction and uac callbacks *              merged in transaction callbacks as LOCAL_COMPLETED (bogdan) *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri) *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced (bogdan) *  2004-08-23  avp support in t_uac (bogdan) */#include <string.h>#include "../../mem/shm_mem.h"#include "../../dprint.h"#include "../../globals.h"#include "../../md5.h"#include "../../crc.h"#include "../../ip_addr.h"#include "../../socket_info.h"#include "ut.h"#include "h_table.h"#include "t_hooks.h"#include "t_funcs.h"#include "t_msgbuilder.h"#include "callid.h"#include "uac.h"#define FROM_TAG_LEN (MD5_LEN + 1 /* - */ + CRC16_LEN) /* length of FROM tags */static char from_tag[FROM_TAG_LEN + 1];char* uac_from = "sip:foo@foo.bar"; /* Module parameter *//* * Initialize UAC */int uac_init(void) {	str src[3];	struct socket_info *si;	if (RAND_MAX < TABLE_ENTRIES) {		LOG(L_WARN, "Warning: uac does not spread "		    "across the whole hash table\n");	}	/* on tcp/tls bind_address is 0 so try to get the first address we listen	 * on no matter the protocol */	si=bind_address?bind_address:get_first_socket();	if (si==0){		LOG(L_CRIT, "BUG: uac_init: null socket list\n");		return -1;	}	/* calculate the initial From tag */	src[0].s = "Long live SER server";	src[0].len = strlen(src[0].s);	src[1].s = si->address_str.s;	src[1].len = strlen(src[1].s);	src[2].s = si->port_no_str.s;	src[2].len = strlen(src[2].s);	MDStringArray(from_tag, src, 3);	from_tag[MD5_LEN] = '-';	return 1;}/* * Generate a From tag */void generate_fromtag(str* tag, str* callid){	     /* calculate from tag from callid */	crcitt_string_array(&from_tag[MD5_LEN + 1], callid, 1);	tag->s = from_tag; 	tag->len = FROM_TAG_LEN;}/* * Check value of parameters */static inline int check_params(str* method, str* to, str* from, dlg_t** dialog){	if (!method || !to || !from || !dialog) {		LOG(L_ERR, "check_params(): Invalid parameter value\n");		return -1;	}	if (!method->s || !method->len) {		LOG(L_ERR, "check_params(): Invalid request method\n");		return -2;	}	if (!to->s || !to->len) {		LOG(L_ERR, "check_params(): Invalid To URI\n");		return -4;	}	if (!from->s || !from->len) {		LOG(L_ERR, "check_params(): Invalid From URI\n");		return -5;	}	return 0;}static inline unsigned int dlg2hash( dlg_t* dlg ){	str cseq_nr;	unsigned int hashid;	cseq_nr.s=int2str(dlg->loc_seq.value, &cseq_nr.len);	hashid=hash(dlg->id.call_id, cseq_nr);	DBG("DEBUG: dlg2hash: %d\n", hashid);	return hashid;}/* * Send a request using data from the dialog structure */int t_uac(str* method, str* headers, str* body, dlg_t* dialog,												transaction_cb cb, void* cbp){	struct socket_info* send_sock;	union sockaddr_union to_su;	struct cell *new_cell;	struct retr_buf *request;	char* buf;	int buf_len;	int ret;	unsigned int hi;	ret=-1;		/*** added by dcm 	 * - needed by external ua to send a request within a dlg	 */	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)		goto error2;	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,			dialog->hooks.next_hop->s);	/* it's a new message, so we will take the default socket */	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE);	if (!send_sock) {		ret=ser_error;		LOG(L_ERR, "t_uac: no socket found\n");		goto error2;	}		new_cell = build_cell(0); 	if (!new_cell) {		ret=E_OUT_OF_MEM;		LOG(L_ERR, "t_uac: short of cell shmem\n");		goto error2;	}	/* better reset avp list now - anyhow, it's useless from	 * this point (bogdan) */	reset_avps();	/* add the callback the the transaction for LOCAL_COMPLETED event */	if(cb && insert_tmcb(&(new_cell->tmcb_hl),TMCB_LOCAL_COMPLETED,cb,cbp)!=1){		ret=E_OUT_OF_MEM;		LOG(L_ERR, "t_uac: short of tmcb shmem\n");		goto error2;	}	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)		new_cell->flags |= T_IS_INVITE_FLAG;	new_cell->flags |= T_IS_LOCAL_FLAG;	set_kr(REQ_FWDED);	request = &new_cell->uac[0].request;	request->dst.to = to_su;	request->dst.send_sock = send_sock;	request->dst.proto = send_sock->proto;	request->dst.proto_reserved1 = 0;	hi=dlg2hash(dialog);	LOCK_HASH(hi);	insert_into_hash_table_unsafe(new_cell, hi);	UNLOCK_HASH(hi);	buf = build_uac_req(method, headers, body, dialog, 0, new_cell,		&buf_len, send_sock);	if (!buf) {		LOG(L_ERR, "t_uac: Error while building message\n");		ret=E_OUT_OF_MEM;		goto error1;	}	new_cell->method.s = buf;	new_cell->method.len = method->len;	request->buffer = buf;	request->buffer_len = buf_len;	new_cell->nr_of_outgoings++;		if (SEND_BUFFER(request) == -1) {		LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", 			dialog->hooks.next_hop->len,			dialog->hooks.next_hop->s);	}		start_retr(request);	return 1; error1:	LOCK_HASH(hi);	remove_from_hash_table_unsafe(new_cell);	UNLOCK_HASH(hi);	free_cell(new_cell);error2:	return ret;}/* * Send a message within a dialog */int req_within(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb completion_cb, void* cbp){	if (!method || !dialog) {		LOG(L_ERR, "req_within: Invalid parameter value\n");		goto err;	}	if (dialog->state != DLG_CONFIRMED) {		LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");		goto err;	}	if ((method->len == 3) && (!memcmp("ACK", method->s, 3))) goto send;	if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;	dialog->loc_seq.value++; /* Increment CSeq */ send:	return t_uac(method, headers, body, dialog, completion_cb, cbp); err:	if (cbp) shm_free(cbp);	return -1;}/* * Send an initial request that will start a dialog */int req_outside(str* method, str* to, str* from, str* headers, str* body, dlg_t** dialog, transaction_cb cb, void* cbp){	str callid, fromtag;	if (check_params(method, to, from, dialog) < 0) goto err;		generate_callid(&callid);	generate_fromtag(&fromtag, &callid);	if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, dialog) < 0) {		LOG(L_ERR, "req_outside(): Error while creating new dialog\n");		goto err;	}	return t_uac(method, headers, body, *dialog, cb, cbp); err:	if (cbp) shm_free(cbp);	return -1;}/* * Send a transactional request, no dialogs involved */int request(str* m, str* ruri, str* to, str* from, str* h, str* b, transaction_cb c, void* cp){	str callid, fromtag;	dlg_t* dialog;	int res;	if (check_params(m, to, from, &dialog) < 0) goto err;	generate_callid(&callid);	generate_fromtag(&fromtag, &callid);	if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &dialog) < 0) {		LOG(L_ERR, "request(): Error while creating temporary dialog\n");		goto err;	}	if (ruri) {		dialog->rem_target.s = ruri->s;		dialog->rem_target.len = ruri->len;		dialog->hooks.request_uri = &dialog->rem_target;	}	w_calculate_hooks(dialog);	res = t_uac(m, h, b, dialog, c, cp);	dialog->rem_target.s = 0;	free_dlg(dialog);	return res; err:	if (cp) shm_free(cp);	return -1;}

⌨️ 快捷键说明

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