示例#1
0
文件: isc.c 项目: 4N7HR4X/kamailio
/**
 *	Forwards the message to the application server.
 * - Marks the message
 * - fills routes
 * - replaces dst_uri
 * @param msg - the SIP message
 * @param m  - the isc_match that matched with info about where to forward it 
 * @param mark  - the isc_mark that should be used to mark the message
 * @returns #ISC_RETURN_TRUE if OK, #ISC_RETURN_ERROR if not
 */
int isc_forward(struct sip_msg *msg, isc_match *m, isc_mark *mark) {
	struct cell *t;
	unsigned int hash, label;
	ticks_t fr_timeout, fr_inv_timeout;
	LM_DBG("marking for AS <%.*s>\n", m->server_name.len, m->server_name.s);

	isc_mark_set(msg, m, mark);
	/* change destination so it forwards to the app server */
	if (msg->dst_uri.s)
		pkg_free(msg->dst_uri.s);
	msg->dst_uri.s = pkg_malloc(m->server_name.len);
	if (!msg->dst_uri.s) {
		LM_ERR("error allocating %d bytes\n", m->server_name.len);
		return ISC_RETURN_ERROR;
	}
	msg->dst_uri.len = m->server_name.len;
	memcpy(msg->dst_uri.s, m->server_name.s, m->server_name.len);

	/* append branch if last trigger failed */
	if (is_route_type(FAILURE_ROUTE))
		append_branch(msg, &(msg->first_line.u.request.uri), &(msg->dst_uri), 0, Q_UNSPECIFIED, 0, 0, 0, 0, 0, 0);

	// Determines the tm transaction identifiers.
	// If no transaction, then creates one

	if (isc_tmb.t_get_trans_ident(msg, &hash, &label) < 0) {
		LM_DBG("SIP message without transaction. OK - first request\n");
		if (isc_tmb.t_newtran(msg) < 0)
			LM_INFO("Failed creating SIP transaction\n");
		if (isc_tmb.t_get_trans_ident(msg, &hash, &label) < 0) {
			LM_INFO("SIP message still without transaction\n");
		} else {
			LM_DBG("New SIP message transaction %u %u\n", hash, label);
		}
	} else {
		LM_INFO("Transaction %u %u exists. Retransmission?\n", hash, label);
	}

	/* set the timeout timers to a lower value */

	t = isc_tmb.t_gett();
	fr_timeout = t->fr_timeout;
	fr_inv_timeout = t->fr_inv_timeout;
	t->fr_timeout = S_TO_TICKS(isc_fr_timeout) / 1000;
	t->fr_inv_timeout = S_TO_TICKS(isc_fr_inv_timeout) / 1000;

	/* send it */
	isc_tmb.t_relay(msg, 0, 0);

	/* recover the timeouts */
	t->fr_timeout = fr_timeout;
	t->fr_inv_timeout = fr_inv_timeout;

	LM_INFO(">>       msg was fwded to AS\n");

	return ISC_RETURN_TRUE;
}
示例#2
0
static int blst_add_f(struct sip_msg* msg, char* to, char* foo)
{
#ifdef USE_DST_BLACKLIST
	int t;
	struct dest_info src;
	
	if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
		t=0;
		if (unlikely( to && (get_int_fparam(&t, msg, (fparam_t*)to)<0)))
			return -1;
		if (t==0)
			t=cfg_get(core, core_cfg, blst_timeout);
		init_dest_info(&src);
		src.send_sock=0;
		src.to=msg->rcv.src_su;
		src.id=msg->rcv.proto_reserved1;
		src.proto=msg->rcv.proto;
		dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg,
									S_TO_TICKS(t));
		return 1;
	}else{
		LOG(L_WARN, "WARNING: blst: blst_add: blacklist support disabled\n");
	}
#else /* USE_DST_BLACKLIST */
	LOG(L_WARN, "WARNING: blst: blst_add: blacklist support not compiled-in"
			" - no effect -\n");
#endif /* USE_DST_BLACKLIST */
	return 1;
}
示例#3
0
文件: isc.c 项目: asyn/openvims
/**
 *	Forwards the message to the application server.
 * - Marks the message
 * - fills routes
 * - replaces dst_uri
 * @param msg - the SIP message
 * @param m  - the isc_match that matched with info about where to forward it 
 * @param mark  - the isc_mark that should be used to mark the message
 * @returns #ISC_RETURN_TRUE if OK, #ISC_RETURN_ERROR if not
 */
int isc_forward( struct sip_msg *msg, isc_match *m,isc_mark *mark)
{
	struct cell *t;
	unsigned int hash,label;
	ticks_t fr_timeout,fr_inv_timeout;
	DBG( "DEBUG:"M_NAME":isc_forward(): marking for AS <%.*s>\n",
		m->server_name.len, m->server_name.s );

	isc_mark_set(msg,m,mark);
	/* change destination so it forwards to the app server */
	if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);
	msg->dst_uri.s = pkg_malloc(m->server_name.len);
	if (!msg->dst_uri.s) {
		LOG(L_ERR,"ERR:"M_NAME":isc_forward(): error allocating %d bytes\n",m->server_name.len);
		return ISC_RETURN_ERROR;
	}
	msg->dst_uri.len = m->server_name.len;
	memcpy(msg->dst_uri.s,m->server_name.s,m->server_name.len);

	/* append branch if last trigger failed */
	if (*isc_tmb.route_mode == MODE_ONFAILURE) 
		append_branch(msg,msg->first_line.u.request.uri.s,msg->first_line.u.request.uri.len,
			msg->dst_uri.s,msg->dst_uri.len,0,0);
	
	/* set the timeout timers to a lower value */
	cscf_get_transaction(msg,&hash,&label);
	t = isc_tmb.t_gett();
	fr_timeout = t->fr_timeout;
	fr_inv_timeout = t->fr_inv_timeout;
	t->fr_timeout=S_TO_TICKS(isc_fr_timeout)/1000;
	t->fr_inv_timeout=S_TO_TICKS(isc_fr_inv_timeout)/1000;
	
	/* send it */
	isc_tmb.t_relay(msg,0,0);
	
	/* recover the timeouts */
	t->fr_timeout=fr_timeout;
	t->fr_inv_timeout=fr_inv_timeout;
	
	LOG(L_INFO,"INFO:"M_NAME">>       msg was fwded to AS\n");
	
//	LOG(L_INFO,"INFO:"M_NAME":isc_forward:   fw relayed with marking [%8X]\n",rc->mark.cnt);
//	DBG( "DEBUG:"M_NAME":isc_forward: Forward sending finished, resuming operation\n" );
	return ISC_RETURN_TRUE;
}
示例#4
0
static int fix_con_lt(void* cfg_h, str* gname, str* name, void** val)
{
	int v;
	v=S_TO_TICKS((int)(long)*val);
	fix_timeout("tls.connection_timeout", &v,
					MAX_TLS_CON_LIFETIME, MAX_TLS_CON_LIFETIME);
	*val=(void*)(long)v;
	return 0;
}
示例#5
0
static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg)
{
	struct sip_msg *shm_msg;
	unsigned int timeout; /* avp timeout gets stored here (in s) */

	shm_msg=new_cell->uas.request;
	new_cell->from.s=shm_msg->from->name.s;
	new_cell->from.len=HF_LEN(shm_msg->from);
	new_cell->to.s=shm_msg->to->name.s;
	new_cell->to.len=HF_LEN(shm_msg->to);
	new_cell->callid.s=shm_msg->callid->name.s;
	new_cell->callid.len=HF_LEN(shm_msg->callid);
	new_cell->cseq_n.s=shm_msg->cseq->name.s;
	new_cell->cseq_n.len=get_cseq(shm_msg)->number.s
		+get_cseq(shm_msg)->number.len
		-shm_msg->cseq->name.s;

	new_cell->method=new_cell->uas.request->first_line.u.request.method;
	if (p_msg->REQ_METHOD==METHOD_INVITE) new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->on_negative=get_on_negative();
	new_cell->on_reply=get_on_reply();
	new_cell->fr_timeout=(ticks_t)get_msgid_val(user_fr_timeout,
												p_msg->id, int);
	new_cell->fr_inv_timeout=(ticks_t)get_msgid_val(user_fr_inv_timeout,
												p_msg->id, int);
	if (new_cell->fr_timeout==0){
		if (!fr_avp2timer(&timeout)) {
			DBG("init_new_t: FR__TIMER = %d s\n", timeout);
			new_cell->fr_timeout=S_TO_TICKS((ticks_t)timeout);
		}else{
			new_cell->fr_timeout=fr_timeout;
		}
	}
	if (new_cell->fr_inv_timeout==0){
		if (!fr_inv_avp2timer(&timeout)) {
			DBG("init_new_t: FR_INV_TIMER = %d s\n", timeout);
			new_cell->fr_inv_timeout=S_TO_TICKS((ticks_t)timeout);
			new_cell->flags |= T_NOISY_CTIMER_FLAG;
		}else{
			new_cell->fr_inv_timeout=fr_inv_timeout;
		}
	}
	new_cell->on_branch=get_on_branch();
}
示例#6
0
/* Adds a new entry to the blacklist */
void dst_blst_add(rpc_t* rpc, void* ctx)
{
	str ip;
	int port, proto, flags;
	unsigned char err_flags;
	struct ip_addr *ip_addr;

	if (!cfg_get(core, core_cfg, use_dst_blacklist)){
		rpc->fault(ctx, 500, "dst blacklist support disabled");
		return;
	}
	if (rpc->scan(ctx, "Sddd", &ip, &port, &proto, &flags) < 4)
		return;

	err_flags = (unsigned char)flags;
	/* sanity checks */
	if ((unsigned char)proto > PROTO_SCTP) {
		rpc->fault(ctx, 400, "Unknown protocol");
		return;
	}

	if (err_flags & BLST_IS_IPV6) {
#ifdef USE_IPV6
		/* IPv6 address is specified */
		ip_addr = str2ip6(&ip);
#else  /* USE_IPV6 */
		rpc->fault(ctx, 400, "IPv6 support disabled");
		return;
#endif /* USE_IPV6 */
	} else {
		/* try IPv4 first, than IPv6 */
		ip_addr = str2ip(&ip);
		if (!ip_addr) {
#ifdef USE_IPV6
			ip_addr = str2ip6(&ip);
			err_flags |= BLST_IS_IPV6;
#else  /* USE_IPV6 */
			rpc->fault(ctx, 400, "Malformed or IPv6 ip address");
			return;
#endif /* USE_IPV6 */
		}
	}
	if (!ip_addr) {
		rpc->fault(ctx, 400, "Malformed ip address");
		return;
	}

	if (dst_blacklist_add_ip(err_flags, proto, ip_addr, port, 
				    S_TO_TICKS(cfg_get(core, core_cfg, blst_timeout))))
		rpc->fault(ctx, 400, "Failed to add the entry to the blacklist");
}
示例#7
0
/* returns error if no retry_after hdr field is present */
static int blst_add_retry_after_f(struct sip_msg* msg, char* min, char* max)
{
#ifdef USE_DST_BLACKLIST
	int t_min, t_max, t;
	struct dest_info src;
	struct hdr_field* hf;
	
	if (likely(cfg_get(core, core_cfg, use_dst_blacklist))){
		if (unlikely(get_int_fparam(&t_min, msg, (fparam_t*)min)<0)) return -1;
		if (likely(max)){
			if (unlikely(get_int_fparam(&t_max, msg, (fparam_t*)max)<0))
				return -1;
		}else{
			t_max=0;
		}
	
		init_dest_info(&src);
		src.send_sock=0;
		src.to=msg->rcv.src_su;
		src.id=msg->rcv.proto_reserved1;
		src.proto=msg->rcv.proto;
		t=-1;
		if ((parse_headers(msg, HDR_RETRY_AFTER_F, 0)==0) && 
			(msg->parsed_flag & HDR_RETRY_AFTER_F)){
			for (hf=msg->headers; hf; hf=hf->next)
				if (hf->type==HDR_RETRY_AFTER_T){
					/* found */
					t=(unsigned)(unsigned long)hf->parsed;
					break;
			}
		}
		if (t<0)
			return -1;
		
		t=MAX_unsigned(t, t_min);
		t=MIN_unsigned(t, t_max);
		if (likely(t))
			dst_blacklist_force_add_to(BLST_ADM_PROHIBITED, &src, msg,
										S_TO_TICKS(t));
		return 1;
	}else{
		LOG(L_WARN, "WARNING: blst: blst_add_retry_after:"
					" blacklist support disabled\n");
	}
#else /* USE_DST_BLACKLIST */
	LOG(L_WARN, "WARNING: blst: blst_add_retry_after:"
			" blacklist support not compiled-in - no effect -\n");
#endif /* USE_DST_BLACKLIST */
	return 1;
}
示例#8
0
int tcpops_set_connection_lifetime(struct tcp_connection* con, int time) {
	if (unlikely(con == NULL)) {
		LM_CRIT("BUG: con == NULL");
		return -1;
	}
	if (unlikely(time < 0)) {
		LM_ERR("Invalid timeout value, %d, must be >= 0\n", time);
		return -1;
	}
	con->lifetime = S_TO_TICKS(time);
	con->timeout = get_ticks_raw() + con->lifetime;
	LM_DBG("new connection lifetime for conid=%d: %d\n", con->id, con->timeout);
	return 1;
}
示例#9
0
/** fix the tls cfg, prior to registering.
  * @return < 0 on error, 0 on success
  */
int fix_tls_cfg(struct cfg_group_tls* cfg)
{
	cfg->con_lifetime = S_TO_TICKS(cfg->con_lifetime);
	fix_timeout("tls_connection_timeout", &cfg->con_lifetime, 
						MAX_TLS_CON_LIFETIME, MAX_TLS_CON_LIFETIME);
	/* Update relative paths of files configured through modparams, relative
	 * pathnames will be converted to absolute and the directory of the main
	 * SER configuration file will be used as reference.
	 */
	if (fix_initial_pathname(&cfg->config_file, 0) < 0)
		return -1;
	if (fix_initial_pathname(&cfg->private_key, TLS_PKEY_FILE) < 0)
		return -1;
	if (fix_initial_pathname(&cfg->ca_list, TLS_CA_FILE) < 0 )
		return -1;
	if (fix_initial_pathname(&cfg->crl, TLS_CRL_FILE) < 0 )
		return -1;
	if (fix_initial_pathname(&cfg->certificate, TLS_CERT_FILE) < 0)
		return -1;
	
	return 0;
}
示例#10
0
文件: timer.c 项目: kamailio/kamailio
/* register a periodic timer;
 * compatibility mode.w/ the old timer interface...
 * ret: <0 on error
 * Hint: if you need it in a module, register it from mod_init or it
 * won't work otherwise*/
int register_timer(timer_function f, void* param, unsigned int interval)
{
	struct sr_timer* t;

	t=shm_malloc(sizeof(struct sr_timer));
	if (t==0){
		SHM_MEM_ERROR;
		goto error;
	}
	t->id=timer_id++;
	t->timer_f=f;
	t->t_param=param;

	timer_init(&t->tl, compat_old_handler, t, 0); /* is slow */
	if (timer_add(&t->tl, S_TO_TICKS(interval))!=0){
		LM_ERR("timer_add failed\n");
		return -1;
	}

	return t->id;

error:
	return E_OUT_OF_MEM;
}
示例#11
0
static int mod_init(void)
{
	int method;

	if (tls_disable){
		LOG(L_WARN, "WARNING: tls: mod_init: tls support is disabled "
				"(set enable_tls=1 in the config to enable it)\n");
		return 0;
	}

	if (cfg_get(tcp, tcp_cfg, async) && !tls_force_run){
		ERR("tls does not support tcp in async mode, please use"
				" tcp_async=no in the config file\n");
		return -1;
	}
	     /* Convert tls_method parameter to integer */
	method = tls_parse_method(&tls_method);
	if (method < 0) {
		ERR("Invalid tls_method parameter value\n");
		return -1;
	}
	mod_params.method = method;

	/* Update relative paths of files configured through modparams, relative
	 * pathnames will be converted to absolute and the directory of the main
	 * SER configuration file will be used as reference.
	 */
	if (fix_rel_pathnames() < 0) return -1;

	tls_cfg = (tls_cfg_t**)shm_malloc(sizeof(tls_cfg_t*));
	if (!tls_cfg) {
		ERR("Not enough shared memory left\n");
		return -1;
	}
	*tls_cfg = NULL;

	register_tls_hooks(&tls_h);
	register_select_table(tls_sel);

	 /* if (init_tls() < 0) return -1; */
	
	tls_cfg_lock = lock_alloc();
	if (tls_cfg_lock == 0) {
		ERR("Unable to create TLS configuration lock\n");
		return -1;
	}
	if (lock_init(tls_cfg_lock) == 0) {
		lock_dealloc(tls_cfg_lock);
		ERR("Unable to initialize TLS configuration lock\n");
		return -1;
	}

	if (tls_cfg_file.s) {
		*tls_cfg = tls_load_config(&tls_cfg_file);
		if (!(*tls_cfg)) return -1;
	} else {
		*tls_cfg = tls_new_cfg();
		if (!(*tls_cfg)) return -1;
	}

	if (tls_check_sockets(*tls_cfg) < 0) return -1;

	/* fix the timeouts from s to ticks */
	if (tls_con_lifetime<0){
		/* set to max value (~ 1/2 MAX_INT) */
		tls_con_lifetime=MAX_TLS_CON_LIFETIME;
	}else{
		if ((unsigned)tls_con_lifetime > 
				(unsigned)TICKS_TO_S(MAX_TLS_CON_LIFETIME)){
			LOG(L_WARN, "tls: mod_init: tls_con_lifetime too big (%u s), "
					" the maximum value is %u\n", tls_con_lifetime,
					TICKS_TO_S(MAX_TLS_CON_LIFETIME));
			tls_con_lifetime=MAX_TLS_CON_LIFETIME;
		}else{
			tls_con_lifetime=S_TO_TICKS(tls_con_lifetime);
		}
	}
	


	return 0;
}
示例#12
0
int init_dst_blacklist()
{
	int ret;
#ifdef BLST_LOCK_PER_BUCKET
	int r;
#endif

	if (dst_blacklist_init==0) {
		/* the dst blacklist is turned off */
		default_core_cfg.use_dst_blacklist=0;
		return 0;
	}

	ret=-1;
#ifdef DST_BLACKLIST_HOOKS
	if (init_blacklist_hooks()!=0){
		ret=E_OUT_OF_MEM;
		goto error;
	}
#endif
	blst_mem_used=shm_malloc(sizeof(*blst_mem_used));
	if (blst_mem_used==0){
		ret=E_OUT_OF_MEM;
		goto error;
	}
	*blst_mem_used=0;
	dst_blst_hash=shm_malloc(sizeof(struct dst_blst_lst_head) *
											DST_BLST_HASH_SIZE);
	if (dst_blst_hash==0){
		ret=E_OUT_OF_MEM;
		goto error;
	}
	memset(dst_blst_hash, 0, sizeof(struct dst_blst_lst_head) *
								DST_BLST_HASH_SIZE);
#ifdef BLST_LOCK_PER_BUCKET
	for (r=0; r<DST_BLST_HASH_SIZE; r++){
		if (lock_init(&dst_blst_hash[r].lock)==0){
			ret=-1;
			goto error;
		}
	}
#elif defined BLST_LOCK_SET
	blst_lock_set=lock_set_alloc(DST_BLST_HASH_SIZE);
	if (blst_lock_set==0){
		ret=E_OUT_OF_MEM;
		goto error;
	}
	if (lock_set_init(blst_lock_set)==0){
		lock_set_dealloc(blst_lock_set);
		blst_lock_set=0;
		ret=-1;
		goto error;
	}
#else /* BLST_ONE_LOCK */
	blst_lock=lock_alloc();
	if (blst_lock==0){
		ret=E_OUT_OF_MEM;
		goto error;
	}
	if (lock_init(blst_lock)==0){
		lock_dealloc(blst_lock);
		blst_lock=0;
		ret=-1;
		goto error;
	}
#endif /* BLST*LOCK*/
	blst_timer_h=timer_alloc();
	if (blst_timer_h==0){
		ret=E_OUT_OF_MEM;
		goto error;
	}
	/* fix options */
	default_core_cfg.blst_max_mem<<=10; /* in Kb */ /* TODO: test with 0 */
	if (blst_timer_interval){
		timer_init(blst_timer_h, blst_timer, 0 ,0); /* slow timer */
		if (timer_add(blst_timer_h, S_TO_TICKS(blst_timer_interval))<0){
			LOG(L_CRIT, "BUG: init_dst_blacklist: failed to add the timer\n");
			timer_free(blst_timer_h);
			blst_timer_h=0;
			goto error;
		}
	}
	return 0;
error:
	destroy_dst_blacklist();
	return ret;
}
示例#13
0
/* handle io routine, based on the fd_map type
 * (it will be called from io_wait_loop* )
 * params:  fm  - pointer to a fd hash entry
 *          idx - index in the fd_array (or -1 if not known)
 * return: -1 on error, or when we are not interested any more on reads
 *            from this fd (e.g.: we are closing it )
 *          0 on EAGAIN or when by some other way it is known that no more 
 *            io events are queued on the fd (the receive buffer is empty).
 *            Usefull to detect when there are no more io events queued for
 *            sigio_rt, epoll_et, kqueue.
 *         >0 on successfull read from the fd (when there might be more io
 *            queued -- the receive buffer might still be non-empty)
 */
inline static int handle_io(struct fd_map* fm, short events, int idx)
{	
	int ret;
	int n;
	int read_flags;
	struct tcp_connection* con;
	int s;
	long resp;
	ticks_t t;
	
	/* update the local config */
	cfg_update();
	
	switch(fm->type){
		case F_TCPMAIN:
again:
			ret=n=receive_fd(fm->fd, &con, sizeof(con), &s, 0);
			LM_DBG("received n=%d con=%p, fd=%d\n", n, con, s);
			if (unlikely(n<0)){
				if (errno == EWOULDBLOCK || errno == EAGAIN){
					ret=0;
					break;
				}else if (errno == EINTR) goto again;
				else{
					LM_CRIT("read_fd: %s \n", strerror(errno));
						abort(); /* big error*/
				}
			}
			if (unlikely(n==0)){
				LM_ERR("0 bytes read\n");
				goto error;
			}
			if (unlikely(con==0)){
					LM_CRIT("null pointer\n");
					goto error;
			}
			con->fd=s;
			if (unlikely(s==-1)) {
				LM_ERR("read_fd: no fd read\n");
				goto con_error;
			}
			con->reader_pid=my_pid();
			if (unlikely(con==tcp_conn_lst)){
				LM_CRIT("duplicate connection received: %p, id %d, fd %d, refcnt %d"
							" state %d (n=%d)\n", con, con->id, con->fd,
							atomic_get(&con->refcnt), con->state, n);
				goto con_error;
				break; /* try to recover */
			}
			if (unlikely(con->state==S_CONN_BAD)){
				LM_WARN("received an already bad connection: %p id %d refcnt %d\n",
							con, con->id, atomic_get(&con->refcnt));
				goto con_error;
			}
			/* if we received the fd there is most likely data waiting to
			 * be read => process it first to avoid extra sys calls */
			read_flags=((con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)) &&
						!(con->flags & F_CONN_OOB_DATA))? RD_CONN_FORCE_EOF
						:0;
#ifdef USE_TLS
repeat_1st_read:
#endif /* USE_TLS */
			resp=tcp_read_req(con, &n, &read_flags);
			if (unlikely(resp<0)){
				/* some error occured, but on the new fd, not on the tcp
				 * main fd, so keep the ret value */
				if (unlikely(resp!=CONN_EOF))
					con->state=S_CONN_BAD;
				LM_WARN("%s:%d %s releasing\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
				release_tcpconn(con, resp, tcpmain_sock);
				break;
			}
#ifdef USE_TLS
			/* repeat read if requested (for now only tls might do this) */
			if (unlikely(read_flags & RD_CONN_REPEAT_READ))
				goto repeat_1st_read;
#endif /* USE_TLS */
			
			/* must be before io_watch_add, io_watch_add might catch some
			 * already existing events => might call handle_io and
			 * handle_io might decide to del. the new connection =>
			 * must be in the list */
			tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev);
			t=get_ticks_raw();
			con->timeout=t+S_TO_TICKS(TCP_CHILD_TIMEOUT);
			/* re-activate the timer */
			con->timer.f=tcpconn_read_timeout;
			local_timer_reinit(&con->timer);
			local_timer_add(&tcp_reader_ltimer, &con->timer,
								S_TO_TICKS(TCP_CHILD_TIMEOUT), t);
			if (unlikely(io_watch_add(&io_w, s, POLLIN, F_TCPCONN, con)<0)){
				LM_CRIT("io_watch_add failed for %p id %d fd %d, state %d, flags %x,"
							" main fd %d, refcnt %d\n",
							con, con->id, con->fd, con->state, con->flags,
							con->s, atomic_get(&con->refcnt));
				tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
				local_timer_del(&tcp_reader_ltimer, &con->timer);
				goto con_error;
			}
			break;
		case F_TCPCONN:
			con=(struct tcp_connection*)fm->data;
			if (unlikely(con->state==S_CONN_BAD)){
				resp=CONN_ERROR;
				if (!(con->send_flags.f & SND_F_CON_CLOSE))
					LM_WARN("F_TCPCONN connection marked as bad: %p id %d refcnt %d\n",
							con, con->id, atomic_get(&con->refcnt));
				goto read_error;
			}
			read_flags=((
#ifdef POLLRDHUP
						(events & POLLRDHUP) |
#endif /* POLLRDHUP */
						(events & (POLLHUP|POLLERR)) |
							(con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)))
						&& !(events & POLLPRI))? RD_CONN_FORCE_EOF: 0;
#ifdef USE_TLS
repeat_read:
#endif /* USE_TLS */
			resp=tcp_read_req(con, &ret, &read_flags);
			if (unlikely(resp<0)){
read_error:
				ret=-1; /* some error occured */
				if (unlikely(io_watch_del(&io_w, con->fd, idx,
											IO_FD_CLOSING) < 0)){
					LM_CRIT("io_watch_del failed for %p id %d fd %d,"
							" state %d, flags %x, main fd %d, refcnt %d\n",
							con, con->id, con->fd, con->state,
							con->flags, con->s, atomic_get(&con->refcnt));
				}
				tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
				local_timer_del(&tcp_reader_ltimer, &con->timer);
				if (unlikely(resp!=CONN_EOF))
					con->state=S_CONN_BAD;
				LM_WARN("%s:%d %s releasing\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
				release_tcpconn(con, resp, tcpmain_sock);
			}else{
#ifdef USE_TLS
				if (unlikely(read_flags & RD_CONN_REPEAT_READ))
						goto repeat_read;
#endif /* USE_TLS */
				/* update timeout */
				con->timeout=get_ticks_raw()+S_TO_TICKS(TCP_CHILD_TIMEOUT);
				/* ret= 0 (read the whole socket buffer) if short read & 
				 *  !POLLPRI,  bytes read otherwise */
				ret&=(((read_flags & RD_CONN_SHORT_READ) &&
						!(events & POLLPRI)) - 1);
			}
			break;
		case F_NONE:
			LM_CRIT("empty fd map %p (%d): {%d, %d, %p}\n",
						fm, (int)(fm-io_w.fd_hash),
						fm->fd, fm->type, fm->data);
			goto error;
		default:
			LM_CRIT("uknown fd type %d\n", fm->type); 
			goto error;
	}
	
	return ret;
con_error:
	con->state=S_CONN_BAD;
	LM_WARN("%s:%d %s releasing\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
	release_tcpconn(con, CONN_ERROR, tcpmain_sock);
	return ret;
error:
	return -1;
}
示例#14
0
int rls_mod_init(void)
{
    load_tm_f load_tm;
	bind_dlg_mod_f bind_dlg;
	struct timer_ln *i_timer = NULL;

	DEBUG_LOG("RLS module initialization\n");

	/* ??? if other module uses this libraries it might be a problem ??? */
	xmlInitParser();

	DEBUG_LOG(" ... common libraries\n");
	qsa_initialize();

	if (time_event_management_init() != 0) {
		LOG(L_ERR, "rls_mod_init(): Can't initialize time event management!\n");
		return -1;
	}

	if (subscription_management_init() != 0) {
		LOG(L_ERR, "rls_mod_init(): Can't initialize time event management!\n");
		return -1;
	}

	/* import the TM auto-loading function */
	if ( !(load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))) {
		LOG(L_ERR, "rls_mod_init(): Can't import tm!\n");
		return -1;
	}
	/* let the auto-loading function load all TM stuff */
	if (load_tm(&tmb)==-1) {
		LOG(L_ERR, "rls_mod_init(): load_tm() failed\n");
		return -1;
	}

	bind_dlg = (bind_dlg_mod_f)find_export("bind_dlg_mod", -1, 0);
	if (!bind_dlg) {
		LOG(L_ERR, "Can't import dlg\n");
		return -1;
	}
	if (bind_dlg(&dlg_func) != 0) {
		return -1;
	}

	if (rls_init() != 0) {
		return -1;
	}

	if (vs_init() != 0) {
		return -1;
	}

/*	xcap_servers = (ptr_vector_t*)mem_alloc(sizeof(ptr_vector_t));
	if (!xcap_servers) {
		LOG(L_ERR, "rls_mod_init(): can't allocate memory for XCAP servers vector\n");
		return -1;
	}
	ptr_vector_init(xcap_servers, 8); */

	/* set authorization type according to requested "auth type name"
	 * and other (type specific) parameters */
	if (set_auth_params(&rls_auth_params, auth_type_str) != 0) return -1;

	use_db = 0;
	if (db_mode > 0) {
		int db_url_len = db_url ? strlen(db_url) : 0;
		if (!db_url_len) {
			LOG(L_ERR, "rls_mod_init(): no db_url specified but db_mode > 0\n");
			db_mode = 0;
		}
	}
	if (db_mode > 0) {
		if (bind_dbmod(db_url, &rls_dbf) < 0) {
			LOG(L_ERR, "rls_mod_init(): Can't bind database module via url %s\n", db_url);
			return -1;
		}

		if (!DB_CAPABILITY(rls_dbf, DB_CAP_ALL)) { /* ? */
			LOG(L_ERR, "rls_mod_init(): Database module does not implement all functions needed by the module\n");
			return -1;
		}
		use_db = 1;
	}

	/* once-shot timer for reloading data from DB -
	 * needed because it can trigger database operations
	 * in other modules and they mostly intialize their 
	 * database connection in child_init functions */
	
	i_timer = timer_alloc();
	if (!i_timer) {
		ERR("can't allocate memory for DB init timer\n");
		return -1;
	}
	else {
		timer_init(i_timer, init_timer_cb, i_timer, 0);
		timer_add(i_timer, S_TO_TICKS(init_timer_delay));
	}
	
	fill_xcap_params = (fill_xcap_params_func)find_export("fill_xcap_params", 0, -1);

	
	return 0;
}