示例#1
0
int wrap_memcached_insert(cachedb_con *con,str* attr, str* value,int expires)
{
	memcached_return_t  rc;
	memcached_con *connection;
	struct timeval start;

	start_expire_timer(start,memcache_exec_threshold);
	connection = (memcached_con *)con->data;

	rc = memcached_set(connection->memc,attr->s, attr->len , value->s,
				value->len, (time_t)expires, (uint32_t)0);

	stop_expire_timer(start,memcache_exec_threshold,
	"cachedb_memcached insert",attr->s,attr->len,0);

	if( rc != MEMCACHED_SUCCESS)
	{
		LM_ERR("Failed to insert: %s\n",memcached_strerror(connection->memc,rc));
		return -1;
	}

	return 0;
}
示例#2
0
static int remove_chunk_f(struct sip_msg* msg, char* glob)
{
	int i;
	str *pat = (str *)glob;
	lcache_entry_t* me1, *me2;
	struct timeval start;

	if (pat->len+1 > pat_buff_size) {
		pat_buff = pkg_realloc(pat_buff,pat->len+1);
		if (pat_buff == NULL) {
			LM_ERR("No more pkg mem\n");
			pat_buff_size = 0;
			return -1;
		}

		pat_buff_size = pat->len +1;
	}

	memcpy(pat_buff,pat->s,pat->len);
	pat_buff[pat->len] = 0;

	LM_DBG("trying to remove chunk with pattern [%s]\n",pat_buff);
	start_expire_timer(start,local_exec_threshold);

	for(i = 0; i< cache_htable_size; i++) {
		lock_get(&cache_htable[i].lock);
		me1 = cache_htable[i].entries;
		me2 = NULL;

		while(me1) {
			if (me1->attr.len + 1 > key_buff_size) {
				key_buff = pkg_realloc(key_buff,me1->attr.len+1);
				if (key_buff == NULL) {
					LM_ERR("No more pkg mem\n");
					key_buff_size = 0;
					lock_release(&cache_htable[i].lock);
					stop_expire_timer(start,local_exec_threshold,
					"cachedb_local remove_chunk",pat->s,pat->len,0);
					return -1;
				}

				key_buff_size = me1->attr.len + 1;
			}

			memcpy(key_buff,me1->attr.s,me1->attr.len);
			key_buff[me1->attr.len] = 0;

			if(fnmatch(pat_buff,key_buff,0) == 0) {
				LM_DBG("[%.*s] matches glob [%.*s] - removing from bucket %d\n",
						me1->attr.len, me1->attr.s,pat_buff_size,pat_buff,i);

				if(me2) {
					me2->next = me1->next;
					shm_free(me1);
					me1 = me2->next;
				} else{
					cache_htable[i].entries = me1->next;
					shm_free(me1);
					me1 = cache_htable[i].entries;
				}
			} else {
				me2 = me1;
				me1 = me1->next;
			}
		}
		lock_release(&cache_htable[i].lock);
	}

	stop_expire_timer(start,local_exec_threshold,
	"cachedb_local remove_chunk",pat->s,pat->len,0);
	return 1;
}
示例#3
0
/*! \brief Finds a tcpconn & sends on it */
static int proto_ws_send(struct socket_info* send_sock,
											char* buf, unsigned int len,
											union sockaddr_union* to, int id)
{
	struct tcp_connection *c;
	struct timeval get;
	struct ip_addr ip;
	int port = 0;
	int fd, n;

	reset_tcp_vars(tcpthreshold);
	start_expire_timer(get,tcpthreshold);

	if (to){
		su2ip_addr(&ip, to);
		port=su_getport(to);
		n = tcp_conn_get(id, &ip, port, &c, &fd);
	}else if (id){
		n = tcp_conn_get(id, 0, 0, &c, &fd);
	}else{
		LM_CRIT("prot_tls_send called with null id & to\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	if (n<0) {
		/* error during conn get, return with error too */
		LM_ERR("failed to aquire connection\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	/* was connection found ?? */
	if (c==0) {
		if (tcp_no_new_conn) {
			return -1;
		}
		LM_DBG("no open tcp connection found, opening new one\n");
		/* create tcp connection */
		if ((c=ws_connect(send_sock, to, &fd))==0) {
			LM_ERR("connect failed\n");
			return -1;
		}
		goto send_it;
	}
	get_time_difference(get, tcpthreshold, tcp_timeout_con_get);

	/* now we have a connection, let's what we can do with it */
	/* BE CAREFUL now as we need to release the conn before exiting !!! */
	if (fd==-1) {
		/* connection is not writable because of its state */
		/* return error, nothing to do about it */
		tcp_conn_release(c, 0);
		return -1;
	}

send_it:
	LM_DBG("sending via fd %d...\n",fd);

	n = ws_req_write(c, fd, buf, len);
	stop_expire_timer(get, tcpthreshold, "WS ops",buf,(int)len,1);
	tcp_conn_set_lifetime( c, tcp_con_lifetime);

	LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd);
	if (n<0){
		LM_ERR("failed to send\n");
		c->state=S_CONN_BAD;
		if (c->proc_id != process_no)
			close(fd);
		tcp_conn_release(c, 0);
		return -1;
	}

	/* only close the FD if not already in the context of our process
	either we just connected, or main sent us the FD */
	if (c->proc_id != process_no)
		close(fd);

	tcp_conn_release(c, 0);
	return n;
}
int couchbase_get_counter(cachedb_con *connection,str *attr,int *val)
{
	lcb_t instance;
	lcb_error_t oprc;
	lcb_get_cmd_t cmd;
	const lcb_get_cmd_t *commands[1];
	struct timeval start;

	start_expire_timer(start,couch_exec_threshold);
	instance = COUCHBASE_CON(connection);

	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.key = attr->s;
	cmd.v.v0.nkey = attr->len;
	oprc = lcb_get(instance, NULL, 1, commands);

	if (oprc != LCB_SUCCESS) {
		/* Key not present, record does not exist */
		if (oprc == LCB_KEY_ENOENT) {
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase get counter",attr->s,attr->len,0);
			return -1;
		}

		//Attempt reconnect
		if (couchbase_conditional_reconnect(connection, oprc) != 1) {
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase get counter ",attr->s,attr->len,0);
			return -2;
		}

		//Try Again
		instance = COUCHBASE_CON(connection);
		oprc = lcb_get(instance, NULL, 1, commands);
		if (oprc != LCB_SUCCESS) {
			if (oprc == LCB_KEY_ENOENT) {
				LM_ERR("Get counter command successfully retried\n");
				stop_expire_timer(start,couch_exec_threshold,
				"cachedb_couchbase get counter",attr->s,attr->len,0);
				return -1;
			}
			LM_ERR("Get counter command retry failed - %s\n", lcb_strerror(instance, oprc));
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase get counter",attr->s,attr->len,0);
			return -2;
		}
		LM_ERR("Get command successfully retried\n");
	}

	//Incase of malloc failure
	if (!get_res.s) {
		stop_expire_timer(start,couch_exec_threshold,
		"cachedb_couchbase get counter",attr->s,attr->len,0);
		return -2;
	}

	stop_expire_timer(start,couch_exec_threshold,
	"cachedb_couchbase get counter",attr->s,attr->len,0);
	
	if (str2sint((str *)&get_res,val)) {
		LM_ERR("Failued to convert counter [%.*s] to int\n",get_res.len,get_res.s);
		pkg_free(get_res.s);
		get_res.s = NULL;
		return -1;
	}

	pkg_free(get_res.s);
	get_res.s = NULL;
	return 1;
}
示例#5
0
/*! \brief Finds a tcpconn & sends on it */
int tcp_send(struct socket_info* send_sock, int type, char* buf, unsigned len,
			union sockaddr_union* to, int id)
{
	struct tcp_connection *c;
	struct tcp_connection *tmp;
	struct ip_addr ip;
	int port;
	int fd;
	long response[2];
	int n;
	struct timeval get,rcv,snd;
	
	port=0;

	reset_tcp_vars(tcpthreshold);
	start_expire_timer(get,tcpthreshold);

	if (to){
		su2ip_addr(&ip, to);
		port=su_getport(to);
		c=tcpconn_get(id, &ip, port, tcp_con_lifetime); 
	}else if (id){
		c=tcpconn_get(id, 0, 0, tcp_con_lifetime);
	}else{
		LM_CRIT("tcp_send called with null id & to\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}
	
	if (id){
		if (c==0) {
			if (to){
				/* try again w/o id */
				c=tcpconn_get(0, &ip, port, tcp_con_lifetime);
				goto no_id;
			}else{
				LM_ERR("id %d not found, dropping\n", id);
				get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
				return -1;
			}
		}else goto get_fd;
	}
no_id:
		if (c==0){
			LM_DBG("no open tcp connection found, opening new one\n");
			/* create tcp connection */
			if ((c=tcpconn_connect(send_sock, to, type))==0){
				LM_ERR("connect failed\n");
				get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
				return -1;
			}
			c->refcnt++; /* safe to do it w/o locking, it's not yet
							available to the rest of the world */
			fd=c->s;
			
			/* send the new tcpconn to "tcp main" */
			response[0]=(long)c;
			response[1]=CONN_NEW;
			n=send_fd(unix_tcp_sock, response, sizeof(response), c->s);
			get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
			if (n<=0){
				LM_ERR("failed send_fd: %s (%d)\n",	strerror(errno), errno);
				n=-1;
				goto end;
			}	
			goto send_it;
		}
get_fd:
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
			/* todo: see if this is not the same process holding
			 *  c  and if so send directly on c->fd */
			LM_DBG("tcp connection found (%p), acquiring fd\n", c);
			/* get the fd */
			response[0]=(long)c;
			response[1]=CONN_GET_FD;
			start_expire_timer(rcv,tcpthreshold);
			n=send_all(unix_tcp_sock, response, sizeof(response));
			if (n<=0){
				LM_ERR("failed to get fd(write):%s (%d)\n",	
						strerror(errno), errno);
				n=-1;
				get_time_difference(rcv,tcpthreshold,tcp_timeout_receive_fd);
				goto release_c;
			}
			LM_DBG("c= %p, n=%d\n", c, n);
			tmp=c;
			n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd, MSG_WAITALL);
			get_time_difference(rcv,tcpthreshold,tcp_timeout_receive_fd);
			if (n<=0){
				LM_ERR("failed to get fd(receive_fd):"
							" %s (%d)\n", strerror(errno), errno);
				n=-1;
				goto release_c;
			}
			if (c!=tmp){
				LM_CRIT("got different connection:"
						"  %p (id= %d, refcnt=%d state=%d != "
						"  %p (id= %d, refcnt=%d state=%d (n=%d)\n",
						  c,   c->id,   c->refcnt,   c->state,
						  tmp, tmp->id, tmp->refcnt, tmp->state, n
				   );
				n=-1; /* fail */
				goto end;
			}
			LM_DBG("after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
		
	
	
send_it:
	LM_DBG("sending...\n");
	lock_get(&c->write_lock);
#ifdef USE_TLS
	if (c->type==PROTO_TLS)
		n=tls_blocking_write(c, fd, buf, len);
	else
#endif
		/* n=tcp_blocking_write(c, fd, buf, len); */
		start_expire_timer(snd,tcpthreshold);
		n=tsend_stream(fd, buf, len, tcp_send_timeout*1000); 
		get_time_difference(snd,tcpthreshold,tcp_timeout_send);
	
		stop_expire_timer(get,tcpthreshold,0,buf,(int)len,1);
	lock_release(&c->write_lock);
	LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd);
	LM_DBG("buf=\n%.*s\n", (int)len, buf);
	if (n<0){
		LM_ERR("failed to send\n");
		/* error on the connection , mark it as bad and set 0 timeout */
		c->state=S_CONN_BAD;
		c->timeout=0;
		/* tell "main" it should drop this (optional it will t/o anyway?)*/
		response[0]=(long)c;
		response[1]=CONN_ERROR;
		n=send_all(unix_tcp_sock, response, sizeof(response));
		/* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put !!*/
		if (n<=0){
			LM_ERR("return failed (write):%s (%d)\n",
					strerror(errno), errno);
		}
		close(fd);
		return -1; /* error return, no tcpconn_put */
	}
end:
	close(fd);
release_c:
	tcpconn_put(c); /* release c (lock; dec refcnt; unlock) */
	return n;
}
示例#6
0
/*! \note WARNING: buf must be 0 terminated (buf[len]=0) or some things might
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
{
	struct sip_msg* msg;
	struct timeval start;
	int rc;
	char *tmp;
	str in_buff;

	in_buff.len = len;
	in_buff.s = buf;

	/* the raw processing callbacks can change the buffer,
	further use in_buff.s and at the end try to free in_buff.s
	if changed by callbacks */
	run_raw_processing_cb(PRE_RAW_PROCESSING,&in_buff);
	/* update the length for further processing */
	len = in_buff.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LM_ERR("no pkg mem left for sip_msg\n");
		goto error;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=in_buff.s;
	msg->len=len;
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;

	if (parse_msg(in_buff.s,len, msg)!=0){
		tmp=ip_addr2a(&(rcv_info->src_ip));
		LM_ERR("Unable to parse msg received from [%s:%d]\n", tmp, rcv_info->src_port);
		/* if a REQUEST msg was detected (first line was succesfully parsed) we
		   should trigger the error route */
		if ( msg->first_line.type==SIP_REQUEST && error_rlist.a!=NULL )
			run_error_route(msg, 1);
		goto parse_error;
	}
	LM_DBG("After parse_msg...\n");

	start_expire_timer(start,execmsgthreshold);

	/* ... clear branches from previous message */
	clear_branches();

	if (msg->first_line.type==SIP_REQUEST) {
		update_stat( rcv_reqs, 1);
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in request\n");
			update_stat( err_reqs, 1);
			goto parse_error;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && tcp_accept_aliases &&
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LM_ERR("tcp alias failed\n");
				/* continue */
			}
		}
#endif

		LM_DBG("preparing to run routing scripts...\n");
		/* set request route type --bogdan*/
		set_route_type( REQUEST_ROUTE );

		/* execute pre-script callbacks, if any;
		 * if some of the callbacks said not to continue with
		 * script processing, don't do so;
		 * if we are here basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		 */
		rc = exec_pre_req_cb(msg);
		if (rc == SCB_DROP_MSG) {
			update_stat( drp_reqs, 1);
			goto end; /* drop the message */
		}

		/* exec the routing script */
		if (rc & SCB_RUN_TOP_ROUTE)
			run_top_route(rlist[DEFAULT_RT].a, msg);

		/* execute post request-script callbacks */
		if (rc & SCB_RUN_POST_CBS)
			exec_post_req_cb(msg);

	} else if (msg->first_line.type==SIP_REPLY) {
		update_stat( rcv_rpls, 1);
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in reply\n");
			update_stat( err_rpls, 1);
			goto parse_error;
		}

		/* set reply route type --bogdan*/
		set_route_type( ONREPLY_ROUTE );

		/* execute pre-script callbacks, if any ;
		 * if some of the callbacks said not to continue with
		 * script processing, don't do so ;
		 * if we are here, basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		 */
		rc = exec_pre_rpl_cb(msg);
		if (rc == SCB_DROP_MSG) {
			update_stat( drp_rpls, 1);
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		if (rc & SCB_RUN_TOP_ROUTE &&  onreply_rlist[DEFAULT_RT].a &&
		    (run_top_route(onreply_rlist[DEFAULT_RT].a,msg) & ACT_FL_DROP)
		    && msg->REPLY_STATUS < 200) {

			LM_DBG("dropping provisional reply %d\n", msg->REPLY_STATUS);
			update_stat( drp_rpls, 1);
			goto end; /* drop the message */
		} else {
			/* send the msg */
			forward_reply(msg);
			/* TODO - TX reply stat */
		}

		/* execute post reply-script callbacks */
		if (rc & SCB_RUN_POST_CBS)
			exec_post_rpl_cb(msg);
	}

end:
	stop_expire_timer( start, execmsgthreshold, "msg processing",
		msg->buf, msg->len, 0);
	reset_longest_action_list(execmsgthreshold);

	/* free possible loaded avps -bogdan */
	reset_avps();
	LM_DBG("cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
	if (in_buff.s != buf)
		pkg_free(in_buff.s);
	return 0;
parse_error:
	exec_parse_err_cb(msg);
	free_sip_msg(msg);
	pkg_free(msg);
error:
	if (in_buff.s != buf)
		pkg_free(in_buff.s);
	return -1;
}
int couchbase_add(cachedb_con *connection,str *attr,int val,int expires,int *new_val)
{
	lcb_t instance;
	lcb_error_t oprc;
	lcb_arithmetic_cmd_t cmd;
	const lcb_arithmetic_cmd_t *commands[1];
	struct timeval start;

	start_expire_timer(start,couch_exec_threshold);
	instance = COUCHBASE_CON(connection);

	commands[0] = &cmd;
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.key = attr->s;
	cmd.v.v0.nkey = attr->len;
	cmd.v.v0.delta = val;
	cmd.v.v0.create = 1;
	cmd.v.v0.initial = val;
	cmd.v.v0.exptime = expires;
	oprc = lcb_arithmetic(instance, NULL, 1, commands);

	if (oprc != LCB_SUCCESS) {
		if (oprc == LCB_KEY_ENOENT) {
			return -1;
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase add",attr->s,attr->len,0);
		}

		LM_ERR("Failed to send the arithmetic query - %s\n", lcb_strerror(instance, oprc));
		//Attempt reconnect
		if (couchbase_conditional_reconnect(connection, oprc) != 1) {
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase add",attr->s,attr->len,0);
			return -2;
		}

		//Try again
		instance = COUCHBASE_CON(connection);
		oprc = lcb_arithmetic(instance, NULL, 1, commands);

		if (oprc != LCB_SUCCESS) {
			if (oprc == LCB_KEY_ENOENT) {
				LM_ERR("Arithmetic command successfully retried\n");
				stop_expire_timer(start,couch_exec_threshold,
				"cachedb_couchbase add",attr->s,attr->len,0);
				return -1;
			}
			LM_ERR("Arithmetic command retry failed - %s\n", lcb_strerror(instance, oprc));
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase add",attr->s,attr->len,0);
			return -2;
		}
		LM_ERR("Arithmetic command successfully retried\n");
	}

	if (new_val)
		*new_val = arithmetic_res;

	stop_expire_timer(start,couch_exec_threshold,
	"cachedb_couchbase add",attr->s,attr->len,0);
	return 1;
}
示例#8
0
/*! \brief Finds a tcpconn & sends on it */
static int proto_tcp_send(struct socket_info* send_sock,
											char* buf, unsigned int len,
											union sockaddr_union* to, int id)
{
	struct tcp_connection *c;
	struct ip_addr ip;
	int port;
	struct timeval get,snd;
	int fd, n;

	port=0;

	reset_tcp_vars(tcpthreshold);
	start_expire_timer(get,tcpthreshold);

	if (to){
		su2ip_addr(&ip, to);
		port=su_getport(to);
		n = tcp_conn_get(id, &ip, port, &c, &fd);
	}else if (id){
		n = tcp_conn_get(id, 0, 0, &c, &fd);
	}else{
		LM_CRIT("tcp_send called with null id & to\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	if (n<0) {
		/* error during conn get, return with error too */
		LM_ERR("failed to acquire connection\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	/* was connection found ?? */
	if (c==0) {
		if (tcp_no_new_conn) {
			return -1;
		}
		LM_DBG("no open tcp connection found, opening new one, async = %d\n",tcp_async);
		/* create tcp connection */
		if (tcp_async) {
			n = tcpconn_async_connect(send_sock, to, buf, len, &c, &fd);
			if ( n<0 ) {
				LM_ERR("async TCP connect failed\n");
				get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
				return -1;
			}
			/* connect succeeded, we have a connection */
			if (n==0) {
				/* connect is still in progress, break the sending
				 * flow now (the actual write will be done when 
				 * connect will be completed */
				LM_DBG("Successfully started async connection \n");
				tcp_conn_release(c, 0);
				return len;
			}

			LM_DBG("First connect attempt succeeded in less than %d ms, "
				"proceed to writing \n",tcp_async_local_connect_timeout);
			/* our first connect attempt succeeded - go ahead as normal */
		} else if ((c=tcp_sync_connect(send_sock, to, &fd))==0) {
			LM_ERR("connect failed\n");
			get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
			return -1;
		}
	
		goto send_it;
	}
	get_time_difference(get,tcpthreshold,tcp_timeout_con_get);

	/* now we have a connection, let's see what we can do with it */
	/* BE CAREFUL now as we need to release the conn before exiting !!! */
	if (fd==-1) {
		/* connection is not writable because of its state - can we append
		 * data to it for later writting (async writting)? */
		if (c->state==S_CONN_CONNECTING) {
			/* the connection is currently in the process of getting
			 * connected - let's append our send chunk as well - just in
			 * case we ever manage to get through */
			LM_DBG("We have acquired a TCP connection which is still "
				"pending to connect - delaying write \n");
			n = add_write_chunk(c,buf,len,1);
			if (n < 0) {
				LM_ERR("Failed to add another write chunk to %p\n",c);
				/* we failed due to internal errors - put the
				 * connection back */
				tcp_conn_release(c, 0);
				return -1;
			}

			/* we successfully added our write chunk - success */
			tcp_conn_release(c, 0);
			return len;
		} else {
			/* return error, nothing to do about it */
			tcp_conn_release(c, 0);
			return -1;
		}
	}


send_it:
	LM_DBG("sending via fd %d...\n",fd);

	start_expire_timer(snd,tcpthreshold);

	n = _tcp_write_on_socket(c, fd, buf, len);

	get_time_difference(snd,tcpthreshold,tcp_timeout_send);
	stop_expire_timer(get,tcpthreshold,"tcp ops",buf,(int)len,1);

	tcp_conn_set_lifetime( c, tcp_con_lifetime);

	LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd);
	/* LM_DBG("buf=\n%.*s\n", (int)len, buf); */
	if (n<0){
		LM_ERR("failed to send\n");
		c->state=S_CONN_BAD;
		if (c->proc_id != process_no)
			close(fd);
		tcp_conn_release(c, 0);
		return -1;
	}

	/* only close the FD if not already in the context of our process
	either we just connected, or main sent us the FD */
	if (c->proc_id != process_no)
		close(fd);

	tcp_conn_release(c, (n<len)?1:0/*pending data in async mode?*/ );
	return n;
}
示例#9
0
文件: hash.c 项目: leedm777/opensips
/*
 *	return :
 *		1  - if found
 *		-2 - if not found
 *		-1 - if error
 * */
int lcache_htable_fetch(cachedb_con *con,str* attr, str* res)
{
	int hash_code;
	lcache_entry_t* it = NULL, *it_aux = NULL;
	char* value;
	struct timeval start;

	start_expire_timer(start,local_exec_threshold);

	hash_code= core_hash( attr, 0, cache_htable_size);
	lock_get(&cache_htable[hash_code].lock);

	it = cache_htable[hash_code].entries;

	while(it)
	{
		if(it->attr.len == attr->len && 
				(strncmp(it->attr.s, attr->s, attr->len) == 0))
		{
			if( it->expires != 0 && it->expires < get_ticks())
			{
				/* found an expired entry  -> delete it */
				if(it_aux)
					it_aux->next = it->next;
				else
					cache_htable[hash_code].entries = it->next;
				
				shm_free(it);

				lock_release(&cache_htable[hash_code].lock);
				stop_expire_timer(start,local_exec_threshold,
				"cachedb_local fetch",attr->s,attr->len,0);
				return -2;
			}
			value = (char*)pkg_malloc(it->value.len);
			if(value == NULL)
			{
				LM_ERR("no more memory\n");
				lock_release(&cache_htable[hash_code].lock);
				stop_expire_timer(start,local_exec_threshold,
				"cachedb_local fetch",attr->s,attr->len,0);
				return -1;
			}
			memcpy(value, it->value.s, it->value.len);
			res->len = it->value.len;
			res->s = value;
			lock_release(&cache_htable[hash_code].lock);
			stop_expire_timer(start,local_exec_threshold,
			"cachedb_local fetch",attr->s,attr->len,0);
			return 1;
		}

		it_aux = it;
		it = it->next;
	}
	
	lock_release(&cache_htable[hash_code].lock);
	stop_expire_timer(start,local_exec_threshold,
	"cachedb_local fetch",attr->s,attr->len,0);
	return -2;
}
示例#10
0
文件: hash.c 项目: leedm777/opensips
int lcache_htable_add(cachedb_con *con,str *attr,int val,int expires,int *new_val) 
{
	int hash_code;
	lcache_entry_t *it=NULL,*it_prev=NULL;
	int old_value;
	char *new_value;
	int new_len;
	str ins_val;
	struct timeval start;

	start_expire_timer(start,local_exec_threshold);

	hash_code = core_hash(attr,0,cache_htable_size);
	lock_get(&cache_htable[hash_code].lock);

	it = cache_htable[hash_code].entries;
	while (it) {
		if (it->attr.len == attr->len && 
				memcmp(it->attr.s,attr->s,attr->len) == 0) {
			if (it->expires !=0 && it->expires < get_ticks()) {
				/* found an expired entry  -> delete it */
				if(it_prev)
					it_prev->next = it->next;
				else
					cache_htable[hash_code].entries = it->next;
				
				shm_free(it);
				lock_release(&cache_htable[hash_code].lock);

				ins_val.s = sint2str(val,&ins_val.len);
				if (lcache_htable_insert(con,attr,&ins_val,expires) < 0) {
					LM_ERR("failed to insert value\n");
					stop_expire_timer(start,local_exec_threshold,
					"cachedb_local add",attr->s,attr->len,0);
					return -1;
				}

				if (new_val)
					*new_val = val;

				stop_expire_timer(start,local_exec_threshold,
				"cachedb_local add",attr->s,attr->len,0);
				return 0;
			}

			/* found our valid entry */
			if (str2sint(&it->value,&old_value) < 0) {
				LM_ERR("not an integer\n");
				lock_release(&cache_htable[hash_code].lock);
				stop_expire_timer(start,local_exec_threshold,
				"cachedb_local add",attr->s,attr->len,0);
				return -1;
			}

			old_value+=val;
			expires = it->expires;
			new_value = sint2str(old_value,&new_len);
			it = shm_realloc(it,sizeof(lcache_entry_t) + attr->len +new_len);
			if (it == NULL) {
				LM_ERR("failed to realloc struct\n");
				lock_release(&cache_htable[hash_code].lock);
				stop_expire_timer(start,local_exec_threshold,
				"cachedb_local add",attr->s,attr->len,0);
				return -1;
			}

			if (it_prev)
				it_prev->next = it;
			else
				cache_htable[hash_code].entries = it;
			
			it->attr.s = (char*)(it + 1);
			it->value.s =(char *)(it + 1) + attr->len;
			it->expires = expires;

			memcpy(it->value.s,new_value,new_len);
			it->value.len = new_len;
			lock_release(&cache_htable[hash_code].lock);
			if (new_val)
				*new_val = old_value;
			stop_expire_timer(start,local_exec_threshold,
			"cachedb_local add",attr->s,attr->len,0);
			return 0;
		}

		it_prev = it;
		it = it->next;
	}

	lock_release(&cache_htable[hash_code].lock);
	
	/* not found */
	ins_val.s = sint2str(val,&ins_val.len);
	if (lcache_htable_insert(con,attr,&ins_val,expires) < 0) {
		LM_ERR("failed to insert value\n");
		stop_expire_timer(start,local_exec_threshold,
		"cachedb_local add",attr->s,attr->len,0);
		return -1;
	}

	if (new_val)
		*new_val = val;
	stop_expire_timer(start,local_exec_threshold,
	"cachedb_local add",attr->s,attr->len,0);
	return 0;
}
示例#11
0
文件: dbase.c 项目: KISSMonX/opensips
static int db_postgres_submit_query(const db_con_t* _con, const str* _s)
{
	int i,ret=0;
	ExecStatusType result;
	PGresult *res = NULL;
	struct timeval start;

	if(! _con || !_s || !_s->s)
	{
		LM_ERR("invalid parameter value\n");
		return(-1);
	}

	submit_func_called = 1;

	/* this bit of nonsense in case our connection get screwed up */
	switch(PQstatus(CON_CONNECTION(_con)))
	{
		case CONNECTION_OK: 
			break;
		case CONNECTION_BAD:
			LM_DBG("connection reset\n");
			PQreset(CON_CONNECTION(_con));
			break;
		case CONNECTION_STARTED:
		case CONNECTION_MADE:
		case CONNECTION_AWAITING_RESPONSE:
		case CONNECTION_AUTH_OK:
		case CONNECTION_SETENV:
		case CONNECTION_SSL_STARTUP:
		case CONNECTION_NEEDED:
		default:
			LM_ERR("%p PQstatus(%s) invalid: %.*s\n", _con,
				PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s);
			return -1;
	}

	for (i=0;i<2;i++) {
		/* free any previous query that is laying about */
		if(CON_RESULT(_con)) {
			free_query(_con);
		}
		start_expire_timer(start,db_postgres_exec_query_threshold);
		ret = PQsendQuery(CON_CONNECTION(_con), _s->s);
		stop_expire_timer(start,db_postgres_exec_query_threshold,"pgsql query",_s->s,_s->len,0);
		/* exec the query */
		if (ret) {
			LM_DBG("%p PQsendQuery(%.*s)\n", _con, _s->len, _s->s);

			while (1) {
				if ((res = PQgetResult(CON_CONNECTION(_con)))) {
					CON_RESULT(_con) = res;
				} else {
					break;
				}
			}

			result = PQresultStatus(CON_RESULT(_con));
			if(result==PGRES_FATAL_ERROR)
				goto reconnect;
			else return 0;
		} else {
reconnect:
			/*  reconnection attempt - if this is the case */
			LM_DBG("%p PQsendQuery failed: %s Query: %.*s\n", _con,
			PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s);
			if(PQstatus(CON_CONNECTION(_con))!=CONNECTION_OK) {
				LM_DBG("connection reset\n");
				PQreset(CON_CONNECTION(_con));
			} else {
				/* failure not due to connection loss - no point in retrying */
				if(CON_RESULT(_con)) {
					free_query(_con);
				}
				break;
			}
		}
	}

	LM_ERR("%p PQsendQuery Error: %s Query: %.*s\n", _con,
	PQerrorMessage(CON_CONNECTION(_con)), _s->len, _s->s);
	return -1;
}
示例#12
0
/*! \brief Finds a tcpconn & sends on it */
static int proto_wss_send(struct socket_info* send_sock,
											char* buf, unsigned int len,
											union sockaddr_union* to, int id)
{
	struct tcp_connection *c;
	struct timeval get;
	struct ip_addr ip;
	int port = 0;
	int fd, n;
	struct ws_data* d;

	reset_tcp_vars(tcpthreshold);
	start_expire_timer(get,tcpthreshold);

	if (to){
		su2ip_addr(&ip, to);
		port=su_getport(to);
		n = tcp_conn_get(id, &ip, port, PROTO_WSS, &c, &fd);
	}else if (id){
		n = tcp_conn_get(id, 0, 0, PROTO_NONE, &c, &fd);
	}else{
		LM_CRIT("prot_tls_send called with null id & to\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	if (n<0) {
		/* error during conn get, return with error too */
		LM_ERR("failed to acquire connection\n");
		get_time_difference(get,tcpthreshold,tcp_timeout_con_get);
		return -1;
	}

	/* was connection found ?? */
	if (c==0) {
		if (tcp_no_new_conn) {
			return -1;
		}
		if (!to) {
			LM_ERR("Unknown destination - cannot open new tcp connection\n");
			return -1;
		}
		LM_DBG("no open tcp connection found, opening new one\n");
		/* create tcp connection */
		if ((c=ws_connect(send_sock, to, &fd))==0) {
			LM_ERR("connect failed\n");
			return -1;
		}
		goto send_it;
	}
	get_time_difference(get, tcpthreshold, tcp_timeout_con_get);

	/* now we have a connection, let's what we can do with it */
	/* BE CAREFUL now as we need to release the conn before exiting !!! */
	if (fd==-1) {
		/* connection is not writable because of its state */
		/* return error, nothing to do about it */
		tcp_conn_release(c, 0);
		return -1;
	}

send_it:
	LM_DBG("sending via fd %d...\n",fd);

	n = ws_req_write(c, fd, buf, len);
	stop_expire_timer(get, tcpthreshold, "WSS ops",buf,(int)len,1);
	tcp_conn_set_lifetime( c, tcp_con_lifetime);

	/* only here we will have all tracing data TLS + WS */
	d = c->proto_data;

	if ( (c->flags&F_CONN_ACCEPTED)==0 && d && d->dest && d->tprot ) {
		if ( d->message ) {
			send_trace_message( d->message, t_dst);
			d->message = NULL;
		}

		/* don't allow future traces for this cnection */
		d->tprot = 0;
		d->dest  = 0;
	}


	LM_DBG("after write: c= %p n=%d fd=%d\n",c, n, fd);
	if (n<0){
		LM_ERR("failed to send\n");
		c->state=S_CONN_BAD;
		if (c->proc_id != process_no)
			close(fd);
		tcp_conn_release(c, 0);
		return -1;
	}

	/* only close the FD if not already in the context of our process
	either we just connected, or main sent us the FD */
	if (c->proc_id != process_no)
		close(fd);

	/* mark the ID of the used connection (tracing purposes) */
	last_outgoing_tcp_id = c->id;

	tcp_conn_release(c, 0);
	return n;
}