Exemplo n.º 1
0
void receive_dlg_binary_packet(int packet_type, struct receive_info *ri, void *att)
{
	int rc;
	char *ip;
	unsigned short port;
	int server_id;

	rc = bin_pop_int(&server_id);
	if (rc < 0)
		return;

	LM_DBG("Received a binary packet!\n");

	if(get_bin_pkg_version() != BIN_VERSION){
		LM_ERR("incompatible bin protocol version\n");
		return;
	}

	if (!accept_replicated_dlg) {
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("Unwanted dialog packet received from %s:%hu (type=%d)\n",
				ip, port, packet_type);
		return;
	}

	if(!clusterer_api.check(accept_replicated_dlg, &ri->src_su, server_id, ri->proto))
		return;

	switch (packet_type) {
	case REPLICATION_DLG_CREATED:
		LM_DBG("AAAA dlg_replicated_create\n");
		rc = dlg_replicated_create(NULL, NULL, NULL, 1);
		if_update_stat(dlg_enable_stats, create_recv, 1);
		break;

	case REPLICATION_DLG_UPDATED:
		LM_DBG("AAAA dlg_replicated_update\n");
		rc = dlg_replicated_update();
		if_update_stat(dlg_enable_stats, update_recv, 1);
		break;

	case REPLICATION_DLG_DELETED:
		LM_DBG("AAAA dlg_replicated_deleted\n");
		rc = dlg_replicated_delete();
		if_update_stat(dlg_enable_stats, delete_recv, 1);
		break;

	default:
		rc = -1;
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("Invalid dialog binary packet command: %d (from %s:%hu)\n",
			packet_type, ip, port);
	}

	if (rc != 0)
		LM_ERR("Failed to process a binary packet!\n");
}
Exemplo n.º 2
0
/**
 * receive_binary_packet (callback) - receives a cmd_type, specifying the
 * purpose of the data encoded in the received UDP packet
 */
void receive_binary_packet(int packet_type, struct receive_info *ri)
{
	int rc;
	char *ip;
	unsigned short port;

	LM_DBG("Received a binary packet!\n");

	if(get_bin_pkg_version() != BIN_VERSION){
		LM_ERR("incompatible bin protocol version\n");
		return;
	}

	if (accept_repl_profiles && packet_type == REPLICATION_DLG_PROFILE) {
		/* TODO: handle this */
		dlg_replicated_profiles(ri);
		return;
	}
	if (!accept_replicated_dlg) {
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("Unwanted dialog packet received from %s:%hu (type=%d)\n",
				ip, port, packet_type);
		return;
	}


	switch (packet_type) {
	case REPLICATION_DLG_CREATED:
		rc = dlg_replicated_create(NULL, NULL, NULL, 1);
		if_update_stat(dlg_enable_stats, create_recv, 1);
		break;

	case REPLICATION_DLG_UPDATED:
		rc = dlg_replicated_update();
		if_update_stat(dlg_enable_stats, update_recv, 1);
		break;

	case REPLICATION_DLG_DELETED:
		rc = dlg_replicated_delete();
		if_update_stat(dlg_enable_stats, delete_recv, 1);
		break;

	default:
		rc = -1;
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("Invalid dialog binary packet command: %d (from %s:%hu)\n",
				packet_type, ip, port);
	}

	if (rc != 0)
		LM_ERR("Failed to process a binary packet!\n");
}
Exemplo n.º 3
0
static void bin_receive_packets(int packet_type, struct receive_info *ri, void *ptr)
{
	struct module_list *module;
	unsigned short port;
	int machine_id;
	char *ip;
	int rc;

	rc = bin_pop_int(&machine_id);
	if (rc < 0)
		return;

	get_su_info(&ri->src_su.s, ip, port);
	LM_DBG("received bin packet from source: %s:%hu\n",
		ip, port);

	module = (struct module_list *) ptr;

	if (module->auth_check) {
		if (!clusterer_check(module->accept_cluster_id, &ri->src_su, machine_id, ri->proto)) {
			get_su_info(&ri->src_su.s, ip, port);
			LM_WARN("received bin packet from unknown source: %s:%hu\n",
				ip, port);
			return;
		}
	}

	rc = set_in_timestamp(module, machine_id);

	if (rc < 0) {
		module->cb(SERVER_TEMP_DISABLED, ri, machine_id);
		return;
	}

	module->cb(packet_type, ri, machine_id);
}
Exemplo n.º 4
0
/**
 * receive_binary_packet (callback) - receives a cmd_type, specifying the
 * purpose of the data encoded in the received UDP packet
 */
void receive_prof_binary_packet(int packet_type, struct receive_info *ri,
																int server_id)
{
	char *ip;
	unsigned short port;

	if (packet_type == SERVER_TEMP_DISABLED) {
		get_su_info(&ri->src_su.s, ip, port);
		LM_INFO("server: %s:%hu temporary disabled\n", ip, port);
		return;
	}

	if (packet_type == SERVER_TIMEOUT) {
		LM_INFO("server with clusterer id %d timeout\n", server_id);
		return;
	}

	if (packet_type != REPLICATION_DLG_PROFILE) {
		LM_WARN("bad packet type\n");
		return;
	}
	dlg_replicated_profiles(ri, server_id);
}
Exemplo n.º 5
0
static int tcpconn_async_connect(struct socket_info* send_sock,
					union sockaddr_union* server, char *buf, unsigned len,
					struct tcp_connection** c, int *ret_fd)
{
	int fd, n;
	union sockaddr_union my_name;
	socklen_t my_name_len;
	struct tcp_connection* con;

	struct pollfd pf;

	unsigned int elapsed,to;
	int err;
	unsigned int err_len;
	int poll_err;
	char *ip;
	unsigned short port;
	struct timeval begin;

	/* create the socket */
	fd = socket(AF2PF(server->s.sa_family), SOCK_STREAM, 0);
	if (fd == -1){
		LM_ERR("socket: (%d) %s\n", errno, strerror(errno));
		return -1;
	}
	if (tcp_init_sock_opt(fd)<0){
		LM_ERR("tcp_init_sock_opt failed\n");
		goto error;
	}
	my_name_len = sockaddru_len(send_sock->su);
	memcpy( &my_name, &send_sock->su, my_name_len);
	su_setport( &my_name, 0);
	if (bind(fd, &my_name.s, my_name_len )!=0) {
		LM_ERR("bind failed (%d) %s\n", errno,strerror(errno));
		goto error;
	}

	/* attempt to do connect and see if we do block or not */
	poll_err = 0;
	elapsed = 0;
	to = hep_async_local_connect_timeout*1000;

	if (gettimeofday(&(begin), NULL)) {
		LM_ERR("Failed to get TCP connect start time\n");
		goto error;
	}

again:
	n = connect(fd, &server->s, sockaddru_len(*server));
	if (n == -1) {
		if (errno == EINTR){
			elapsed=get_time_diff(&begin);
			if (elapsed < to) goto again;
			else {
				LM_DBG("Local connect attempt failed \n");
				goto async_connect;
			}
		}
		if (errno != EINPROGRESS && errno!=EALREADY) {
			get_su_info(&server->s, ip, port);
			LM_ERR("[server=%s:%d] (%d) %s\n",ip, port, errno,strerror(errno));
			goto error;
		}
	} else goto local_connect;

	/* let's poll for a little */

	pf.fd = fd;
	pf.events = POLLOUT;

	while(1){
		elapsed = get_time_diff(&begin);
		if (elapsed < to)
			to -= elapsed;
		else {
			LM_DBG("Polling is overdue \n");
			goto async_connect;
		}

		n = poll(&pf, 1, to/1000);

		if (n < 0){
			if (errno == EINTR) continue;
			get_su_info(&server->s, ip, port);
			LM_ERR("poll/select failed:[server=%s:%d] (%d) %s\n",
				ip, port, errno, strerror(errno));
			goto error;
		} else if (n==0) /* timeout */ continue;

		if (pf.revents & (POLLERR|POLLHUP|POLLNVAL)){
			LM_ERR("poll error: flags %x\n", pf.revents);
			poll_err=1;
		}


		err_len=sizeof(err);
		getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
		if ((err==0) && (poll_err==0)) goto local_connect;
		if (err!=EINPROGRESS && err!=EALREADY){
			get_su_info(&server->s, ip, port);
			LM_ERR("failed to retrieve SO_ERROR [server=%s:%d] (%d) %s\n",
				ip, port, err, strerror(err));
			goto error;
		}
	}

async_connect:
	LM_DBG("Create connection for async connect\n");
	/* create a new dummy connection */
	con = tcp_conn_create(fd, server, send_sock, S_CONN_CONNECTING);
	if (con==NULL) {
		LM_ERR("tcp_conn_create failed\n");
		goto error;
	}

	/* attach the write buffer to it */
	lock_get(&con->write_lock);

	if (add_write_chunk(con,buf,len,0) < 0) {
		LM_ERR("Failed to add the initial write chunk\n");
		/* FIXME - seems no more SHM now ...
		 * continue the async connect process ? */
	}

	lock_release(&con->write_lock);
	/* report an async, in progress connect */
	*c = con;
	return 0;

local_connect:
	con = tcp_conn_create(fd, server, send_sock, S_CONN_OK);
	if (con==NULL) {
		LM_ERR("tcp_conn_create failed, closing the socket\n");
		goto error;
	}
	*c = con;
	*ret_fd = fd;
	/* report a local connect */
	return 1;

error:
	close(fd);
	*c = NULL;
	return -1;
}
Exemplo n.º 6
0
int tcp_connect_blocking(int fd, const struct sockaddr *servaddr,
															socklen_t addrlen)
{
	int n;
#if defined(HAVE_SELECT) && defined(BLOCKING_USE_SELECT)
	fd_set sel_set;
	fd_set orig_set;
	struct timeval timeout;
#else
	struct pollfd pf;
#endif
	int elapsed;
	int to;
	int err;
	struct timeval begin;
	unsigned int err_len;
	int poll_err;
	char *ip;
	unsigned short port;

	poll_err=0;
	to = tcp_connect_timeout*1000;

	if (gettimeofday(&(begin), NULL)) {
		LM_ERR("Failed to get TCP connect start time\n");
		goto error;
	}

again:
	n=connect(fd, servaddr, addrlen);
	if (n==-1){
		if (errno==EINTR){
			elapsed=get_time_diff(&begin);
			if (elapsed<to) goto again;
			else goto error_timeout;
		}
		if (errno!=EINPROGRESS && errno!=EALREADY){
			get_su_info( servaddr, ip, port);
			LM_ERR("[server=%s:%d] (%d) %s\n",ip, port, errno, strerror(errno));
			goto error;
		}
	}else goto end;

	/* poll/select loop */
#if defined(HAVE_SELECT) && defined(BLOCKING_USE_SELECT)
		FD_ZERO(&orig_set);
		FD_SET(fd, &orig_set);
#else
		pf.fd=fd;
		pf.events=POLLOUT;
#endif
	while(1){
		elapsed = get_time_diff(&begin);
		if (elapsed<to)
			to-=elapsed;
		else
			goto error_timeout;
#if defined(HAVE_SELECT) && defined(BLOCKING_USE_SELECT)
		sel_set=orig_set;
		timeout.tv_sec = to/1000000;
		timeout.tv_usec = to%1000000;
		n=select(fd+1, 0, &sel_set, 0, &timeout);
#else
		n=poll(&pf, 1, to/1000);
#endif
		if (n<0){
			if (errno==EINTR) continue;
			get_su_info( servaddr, ip, port);
			LM_ERR("poll/select failed:[server=%s:%d] (%d) %s\n",
				ip, port, errno, strerror(errno));
			goto error;
		}else if (n==0) /* timeout */ continue;
#if defined(HAVE_SELECT) && defined(BLOCKING_USE_SELECT)
		if (FD_ISSET(fd, &sel_set))
#else
		if (pf.revents&(POLLERR|POLLHUP|POLLNVAL)){
			LM_ERR("poll error: flags %d - %d %d %d %d \n", pf.revents,
				   POLLOUT,POLLERR,POLLHUP,POLLNVAL);
			poll_err=1;
		}
#endif
		{
			err_len=sizeof(err);
			getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
			if ((err==0) && (poll_err==0)) goto end;
			if (err!=EINPROGRESS && err!=EALREADY){
				get_su_info( servaddr, ip, port);
				LM_ERR("failed to retrieve SO_ERROR [server=%s:%d] (%d) %s\n",
					ip, port, err, strerror(err));
				goto error;
			}
		}
	}
error_timeout:
	/* timeout */
	LM_ERR("timeout %d ms elapsed from %d s\n", elapsed,
		tcp_connect_timeout*1000);
error:
	return -1;
end:
	return 0;
}
Exemplo n.º 7
0
void rl_rcv_bin(int packet_type, struct receive_info *ri)
{
	rl_algo_t algo;
	int limit;
	int counter;
	str name;
	int index;
	char *ip;
	unsigned short port;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;

	if (packet_type != RL_PIPE_COUNTER)
		return;

	/* match the server */
	for (index = 0; index < rl_dests_nr; index++) {
		 if (su_cmp(&ri->src_su, &rl_dests[index].to))
			break;
	}

	if (index == rl_dests_nr) {
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("received bin packet from unknown source: %s:%hu\n",
				ip, port);
		return;
	}
	now = time(0);
	*rl_dests[index].last_msg = now;

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(&algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(&limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, alocate it in case we need it later */
			*pipe = shm_malloc(sizeof(rl_pipe_t) +
					rl_dests_nr * sizeof(rl_repl_counter_t));
			if (!*pipe) {
				LM_ERR("no more shm memory\n");
				goto release;
			}
			memset(*pipe, 0, sizeof(rl_pipe_t) +
					rl_dests_nr * sizeof(rl_repl_counter_t));
			(*pipe)->dsts = (rl_repl_counter_t *)((*pipe) + 1);
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
					name.len, name.s, *pipe);
			(*pipe)->algo = algo;
			(*pipe)->limit = limit;
		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
					name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
						"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
						"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		(*pipe)->dsts[index].counter = counter;
		(*pipe)->dsts[index].update = now;

		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}
Exemplo n.º 8
0
static void dlg_replicated_profiles(struct receive_info *ri)
{
	int index;
	time_t now;
	str name;
	str value;
	char *ip;
	unsigned short port;
	unsigned int counter;
	struct dlg_profile_table *profile;
	int has_value;
	int i;
	void **dst;
	repl_prof_value_t *rp;

	/* optimize profile search */
	struct dlg_profile_table *old_profile = NULL;
	str old_name;

	/* match the server */
	for (index = 0; index < repl_prof_dests_nr; index++) {
		 if (su_cmp(&ri->src_su, &repl_prof_dests[index].to))
			break;
	}

	if (index == repl_prof_dests_nr) {
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("received bin packet from unknown source: %s:%hu\n",
				ip, port);
		return;
	}
	now = time(0);
	*repl_prof_dests[index].last_msg = now;

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		/* check if the same profile was sent */
		if (!old_profile || old_name.len != name.len ||
				memcmp(name.s, old_name.s, name.len) != 0) {
			old_profile = get_dlg_profile(&name);
			if (!old_profile) {
				get_su_info(&ri->src_su.s, ip, port);
				LM_WARN("received unknown profile <%.*s> from %s:%hu\n",
						name.len, name.s, ip, port);
			}
			old_name = name;
		}
		profile = old_profile;

		if (bin_pop_int(&has_value) < 0) {
			LM_ERR("cannot pop profile's has_value int\n");
			return;
		}
		
		if (has_value) {
			if (!profile->has_value) {
				get_su_info(&ri->src_su.s, ip, port);
				LM_WARN("The other end does not have a value for this profile:"
						"<%.*s> [%s:%hu]\n", profile->name.len, profile->name.s, ip, port);
				profile = NULL;
			}
			if (bin_pop_str(&value)) {
				LM_ERR("cannot pop the value of the profile\n");
				return;
			}
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop profile's counter\n");
			return;
		}

		if (profile) {
			if (!profile->has_value) {
				lock_get(&profile->repl->lock);
				profile->repl->dsts[index].counter = counter;
				profile->repl->dsts[index].update = now;
				lock_release(&profile->repl->lock);
			} else {
				/* XXX: hack to make sure we find the proper index */
				i = core_hash(&value, NULL, profile->size);
				lock_set_get(profile->locks, i);
				/* if counter is 0 and we don't have it, don't try to create */
				if (!counter) {
					dst = map_find(profile->entries[i], value);
					if (!dst)
						goto release;
				} else {
					dst = map_get(profile->entries[i], value);
				}
				if (!*dst) {
					rp = shm_malloc(sizeof(repl_prof_value_t));
					if (!rp) {
						LM_ERR("no more shm memory to allocate repl_prof_value\n");
						goto release;
					}
					memset(rp, 0, sizeof(repl_prof_value_t));
					*dst = rp;
				} else {
					rp = (repl_prof_value_t *)*dst;
				}
				if (!rp->noval)
					rp->noval = repl_prof_allocate();
				if (rp->noval) {
					lock_release(&rp->noval->lock);
					rp->noval->dsts[index].counter = counter;
					rp->noval->dsts[index].update = now;
					lock_release(&rp->noval->lock);
				}
release:
				lock_set_release(profile->locks, i);
			}
		}
	}
	return;
}
Exemplo n.º 9
0
void rl_rcv_bin(int packet_type, struct receive_info *ri, int server_id)
{
	rl_algo_t algo;
	int limit;
	int counter;
	str name;
	char *ip;
	unsigned short port;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;
	rl_repl_counter_t *destination;
	
	if (packet_type == SERVER_TEMP_DISABLED) {
 		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("server: %s:%hu temporary disabled\n", ip, port);
 		return;
 	}

	if (packet_type == SERVER_TIMEOUT) {
		LM_WARN("server with clustererer id %d timeout\n", server_id);
		return;
	}
	
	if(get_bin_pkg_version() != BIN_VERSION){
		LM_ERR("incompatible bin protocol version\n");
		return;
	}

	if (packet_type != RL_PIPE_COUNTER)
		return;

	if (packet_type != RL_PIPE_COUNTER)
		return;

	now = time(0);

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(&algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(&limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, alocate it in case we need it later */
			*pipe = shm_malloc(sizeof(rl_pipe_t));
			if (!*pipe) {
				LM_ERR("no more shm memory\n");
				goto release;
			}
			memset(*pipe, 0, sizeof(rl_pipe_t));
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
				name.len, name.s, *pipe);
			(*pipe)->algo = algo;
			(*pipe)->limit = limit;
		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
				name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
				"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
				"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		destination = find_destination(*pipe, server_id);
		destination->counter = counter;
		destination->update = now;
		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}
Exemplo n.º 10
0
void rl_rcv_bin(int packet_type, struct receive_info *ri)
{
	rl_algo_t algo;
	int limit;
	int counter;
	int rc;
	int server_id;
	str name;
	char *ip;
	unsigned short port;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;
	rl_repl_counter_t *destination;

	LM_DBG("received a binary packet [%d]!\n", packet_type);
	
	if (packet_type != RL_PIPE_COUNTER)
		return;
	
	rc = bin_pop_int(&server_id);
	if (rc < 0)
		return;
	
	if (!clusterer_api.check(accept_repl_pipes, &ri->src_su, server_id, ri->proto)){
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("received bin packet from unknown source: %s:%hu\n",
				ip, port);
		return;
	}
	now = time(0);

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(&algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(&limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, alocate it in case we need it later */
			*pipe = shm_malloc(sizeof(rl_pipe_t));
			if (!*pipe) {
				LM_ERR("no more shm memory\n");
				goto release;
			}
			memset(*pipe, 0, sizeof(rl_pipe_t));
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
					name.len, name.s, *pipe);
			(*pipe)->algo = algo;
			(*pipe)->limit = limit;
		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
					name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
						"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
						"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		destination = find_destination(*pipe, server_id);
		destination->counter = counter;
		destination->update = now;
		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}