예제 #1
0
파일: handlers.c 프로젝트: idtek/knot
int event_refresh(conf_t *conf, zone_t *zone)
{
	assert(zone);

	/* Ignore if not slave zone. */
	if (!zone_is_slave(conf, zone)) {
		return KNOT_EOK;
	}

	if (zone_contents_is_empty(zone->contents)) {
		/* No contents, schedule retransfer now. */
		zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW);
		return KNOT_EOK;
	}

	int ret = zone_master_try(conf, zone, try_refresh, NULL, "refresh");
	const knot_rdataset_t *soa = zone_soa(zone);
	if (ret != KNOT_EOK) {
		log_zone_error(zone->name, "refresh, failed (%s)",
		               knot_strerror(ret));
		/* Schedule next retry. */
		zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_retry(soa));
		start_expire_timer(conf, zone, soa);
	} else {
		/* SOA query answered, reschedule refresh timer. */
		zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_refresh(soa));
	}

	return KNOT_EOK;
}
예제 #2
0
파일: hash.c 프로젝트: leedm777/opensips
int lcache_htable_fetch_counter(cachedb_con* con,str* attr,int *val)
{
	int hash_code;
	lcache_entry_t* it = NULL, *it_aux = NULL;
	int ret;
	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_counter",attr->s,attr->len,0);
				return -2;
			}
			if (str2sint(&it->value,&ret) != 0) {
				LM_ERR("Not a counter key\n");
				lock_release(&cache_htable[hash_code].lock);
				stop_expire_timer(start,local_exec_threshold,
				"cachedb_local fetch_counter",attr->s,attr->len,0);
				return -3;
			}
			if (val)
				*val = ret;
			lock_release(&cache_htable[hash_code].lock);
			stop_expire_timer(start,local_exec_threshold,
			"cachedb_local fetch_counter",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_counter",attr->s,attr->len,0);
	return -2;
}
예제 #3
0
파일: dbase.c 프로젝트: OpenSIPS/opensips
/**
 * Begins execution of a raw SQL query. Returns immediately.
 *
 * \param _h handle for the database
 * \param _s raw query string
 * \param _priv internal parameter; holds the conn that the query is bound to
 * \return
 *		success: Unix FD for polling
 *		failure: negative error code
 */
int db_postgres_async_raw_query(db_con_t *_h, const str *_s, void **_priv)
{
	int *fd_ref;
	int code;
	struct timeval start;
	struct my_con *con;

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

	con = (struct my_con *)db_init_async(_h, db_postgres_get_con_fd,
	                           &fd_ref, (void *)db_postgres_new_async_connection);
	*_priv = con;
	if (!con)
		LM_INFO("Failed to open new connection (current: 1 + %d). Running "
				"in sync mode!\n", ((struct pool_con *)_h->tail)->no_transfers);

	/* no prepared statements support */
	CON_RESET_CURR_PS(_h);
	start_expire_timer(start, db_postgres_exec_query_threshold);

	/* async mode */
	if (con) {
		code = db_postgres_submit_async_query(_h, _s);
	/* sync mode */
	} else {
		code = db_postgres_submit_query(_h, _s);
	}
	_stop_expire_timer(start, db_postgres_exec_query_threshold,
		"pgsql async query", _s->s, _s->len, 0,
		sql_slow_queries, sql_total_queries);

	if (code < 0) {
		LM_ERR("failed to send postgres query %.*s",_s->len,_s->s);
		goto out;
	} else {
		/* success */
		if (!con)
			return -1;

		*fd_ref = db_postgres_get_con_fd(con);
		db_switch_to_sync(_h);
		return *fd_ref;
	}

out:
	if (!con)
		return -1;

	db_switch_to_sync(_h);
	db_store_async_con(_h, (struct pool_con *)con);

	return -2;
}
예제 #4
0
int wrap_memcached_get(cachedb_con *connection,str* attr, str* res)
{
	memcached_return_t  rc;
	char * ret;
	size_t ret_len;
	uint32_t fl;
	char * err;
	char * value;
	memcached_con *con;
	struct timeval start;

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

	ret = memcached_get(con->memc,attr->s, attr->len,
				&ret_len,&fl,&rc);

	if(ret == NULL)
	{
		if(rc == MEMCACHED_NOTFOUND)
		{
			res->s = NULL;
			res->len = 0;
			stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached get",attr->s,attr->len,0);
			return -2;
		}
		else
		{
			err = (char*)memcached_strerror(con->memc,rc);
			LM_ERR("Failed to get: %s\n",err );
			stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached get",attr->s,attr->len,0);
			return -1;
		}
	}

	value = pkg_malloc(ret_len);
	if( value == NULL)
	{
		LM_ERR("Memory allocation");
		stop_expire_timer(start,memcache_exec_threshold,
		"cachedb_memcached get",attr->s,attr->len,0);
		return -1;
	}

	memcpy(value,ret,ret_len);
	res->s = value;
	res->len = ret_len;

	free(ret);

	stop_expire_timer(start,memcache_exec_threshold,
	"cachedb_memcached get",attr->s,attr->len,0);
	return 0;
}
예제 #5
0
int couchbase_remove(cachedb_con *connection,str *attr)
{
	lcb_t instance;
	lcb_error_t oprc;
	lcb_remove_cmd_t cmd;
	const lcb_remove_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_remove(instance, NULL, 1, commands);

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

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

		instance = COUCHBASE_CON(connection);
		oprc = lcb_remove(instance, NULL, 1, commands);

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

	LM_DBG("Succesfully removed\n");
	stop_expire_timer(start,couch_exec_threshold,
	"cachedb_couchbase remove",attr->s,attr->len,0);
	return 1;
}
예제 #6
0
int wrap_memcached_get_counter(cachedb_con *connection,str* attr, int* res)
{
	memcached_return_t  rc;
	char * ret;
	size_t ret_len;
	uint32_t fl;
	char * err;
	memcached_con *con;
	struct timeval start;
	str rpl;

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

	ret = memcached_get(con->memc,attr->s, attr->len,
				&ret_len,&fl,&rc);

	if(ret == NULL)
	{
		if(rc == MEMCACHED_NOTFOUND)
		{
			stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached counter fetch",attr->s,attr->len,0);
			return -2;
		}
		else
		{
			err = (char*)memcached_strerror(con->memc,rc);
			LM_ERR("Failed to get: %s\n",err );
			stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached counter fetch",attr->s,attr->len,0);
			return -1;
		}
	}

	rpl.len = (int)ret_len;
	rpl.s = ret;
	
	if (str2sint(&rpl,res) < 0) {
		LM_ERR("Failed to convert %.*s to int\n",(int)ret_len,ret);
		stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached counter fetch",attr->s,attr->len,0);
		free(ret);
		return -1;
		
	}

	stop_expire_timer(start,memcache_exec_threshold,
		"cachedb_memcached counter fetch",attr->s,attr->len,0);
	free(ret);
	return 0;
}
예제 #7
0
int couchbase_set(cachedb_con *connection,str *attr,
		str *val,int expires)
{
	lcb_t instance;
	lcb_error_t oprc;
	lcb_store_cmd_t cmd;
	const lcb_store_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.operation = LCB_SET;
	cmd.v.v0.key = attr->s;
	cmd.v.v0.nkey = attr->len;
	cmd.v.v0.bytes = val->s;
	cmd.v.v0.nbytes = val->len;
	cmd.v.v0.exptime = expires;

	oprc = lcb_store(instance, NULL, 1, commands);

	if (oprc != LCB_SUCCESS) {
		LM_ERR("Set request failed - %s\n", lcb_strerror(instance, oprc));
		//Attempt reconnect
		if(couchbase_conditional_reconnect(connection, oprc) != 1) {
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase set",attr->s,attr->len,0);
			return -2;
		}

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

		if (oprc != LCB_SUCCESS) {
			LM_ERR("Set command retry failed - %s\n", lcb_strerror(instance, oprc));
			stop_expire_timer(start,couch_exec_threshold,
			"cachedb_couchbase set",attr->s,attr->len,0);
			return -2;
		}
		LM_ERR("Set command successfully retried\n");
	}
	LM_DBG("Succesfully stored\n");
	stop_expire_timer(start,couch_exec_threshold,
	"cachedb_couchbase set",attr->s,attr->len,0);
	return 1;
}
예제 #8
0
파일: hash.c 프로젝트: leedm777/opensips
int lcache_htable_insert(cachedb_con *con,str* attr, str* value, int expires)
{
	lcache_entry_t* me, *it;
	int hash_code;
	int size;
	struct timeval start;

	size= sizeof(lcache_entry_t) + attr->len + value->len;

	me = (lcache_entry_t*)shm_malloc(size);
	if(me == NULL)
	{
		LM_ERR("no more shared memory\n");
		return -1;
	}
	memset(me, 0, size);

	start_expire_timer(start,local_exec_threshold);

	me->attr.s = (char*)me + (sizeof(lcache_entry_t));
	memcpy(me->attr.s, attr->s, attr->len);
	me->attr.len = attr->len;

	me->value.s = (char*)me + (sizeof(lcache_entry_t)) + attr->len;
	memcpy(me->value.s, value->s, value->len);
	me->value.len = value->len;
	if( expires != 0)
		me->expires = get_ticks() + expires;

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

	it = cache_htable[hash_code].entries;

	/* if a previous record for the same attr delete it */
	lcache_htable_remove_safe( *attr, &it);

	me->next = it;
	cache_htable[hash_code].entries = me;

	lock_release(&cache_htable[hash_code].lock);

	stop_expire_timer(start,local_exec_threshold,
	"cachedb_local insert",attr->s,attr->len,0);
	return 1;
}
예제 #9
0
/* TODO - once memcached_touch gets into libmemcached, also take care of expires */
int wrap_memcached_sub(cachedb_con *connection,str* attr,int val,
		int expires,int *new_val)
{
	memcached_return_t  rc;
	memcached_con *con;
	uint64_t res;
	str ins_val;
	struct timeval start;

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

	rc = memcached_decrement(con->memc,attr->s,attr->len,val,&res);

	if( rc != MEMCACHED_SUCCESS ) {
		if (rc == MEMCACHED_NOTFOUND) {
			ins_val.s = sint2str(val,&ins_val.len);
			if (wrap_memcached_insert(connection,attr,&ins_val,expires) < 0) {
				LM_ERR("failed to insert value\n");
				stop_expire_timer(start,memcache_exec_threshold,
				"cachedb_memcached sub",attr->s,attr->len,0);
				return -1;
			}
			if (new_val)
				*new_val = val;

			stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached sub",attr->s,attr->len,0);
			return 0;
		} else {
			LM_ERR("Failed to sub: %s\n",memcached_strerror(con->memc,rc));
			stop_expire_timer(start,memcache_exec_threshold,
			"cachedb_memcached sub",attr->s,attr->len,0);
			return -1;
		}
	}

	if (new_val)
		*new_val = (int)res;

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

	return 0;
}
예제 #10
0
파일: hash.c 프로젝트: leedm777/opensips
int lcache_htable_remove(cachedb_con *con,str* attr)
{
	int hash_code;
	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);

	lcache_htable_remove_safe( *attr, &cache_htable[hash_code].entries);

	lock_release(&cache_htable[hash_code].lock);

	stop_expire_timer(start,local_exec_threshold,
	"cachedb_local remove",attr->s,attr->len,0);

	return 0;
}
예제 #11
0
static int wss_raw_writev(struct tcp_connection *c, int fd,
		const struct iovec *iov, int iovcnt, int tout)
{
	struct timeval snd;
	int i, n, ret = 0;
#ifdef TLS_DONT_WRITE_FRAGMENTS
	static char *buf = NULL;
#endif

	start_expire_timer(snd,tcpthreshold);

#ifndef TLS_DONT_WRITE_FRAGMENTS
	for (i = 0; i < iovcnt; i++) {
		n = tls_blocking_write(c, fd, iov[i].iov_base, iov[i].iov_len, &tls_mgm_api);
		if (n < 0) {
			ret = -1;
			goto end;
		}
		ret += n;
	}
#else
	n = 0;
	for (i = 0; i < iovcnt; i++)
		n += iov[i].iov_len;
	buf = pkg_realloc(buf, n);
	if (!buf) {
		ret = -2;
		goto end;
	}
	n = 0;
	for (i = 0; i < iovcnt; i++) {
		memcpy(buf + n, iov[i].iov_base, iov[i].iov_len);
		n += iov[i].iov_len;
	}
	n = tls_blocking_write(c, fd, buf, n, &tls_mgm_api);

#endif /* TLS_DONT_WRITE_FRAGMENTS */

end:
	get_time_difference(snd, tcpthreshold, tout);
	return ret;
}
예제 #12
0
int wrap_memcached_remove(cachedb_con *connection,str* attr)
{
	memcached_return_t  rc;
	memcached_con *con;
	struct timeval start;

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

	rc = memcached_delete(con->memc,attr->s,attr->len,0);

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

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

	return 0;
}
예제 #13
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;
}
예제 #14
0
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;
}
예제 #15
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;
}
예제 #16
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;
}
예제 #17
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;
}
예제 #18
0
파일: handlers.c 프로젝트: idtek/knot
int event_xfer(conf_t *conf, zone_t *zone)
{
	assert(zone);

	/* Ignore if not slave zone. */
	if (!zone_is_slave(conf, zone)) {
		return KNOT_EOK;
	}

	struct transfer_data data = { 0 };
	const char *err_str = "";

	/* Determine transfer type. */
	bool is_bootstrap = zone_contents_is_empty(zone->contents);
	if (is_bootstrap || zone->flags & ZONE_FORCE_AXFR) {
		data.pkt_type = KNOT_QUERY_AXFR;
		err_str = "AXFR, incoming";
	} else {
		data.pkt_type = KNOT_QUERY_IXFR;
		err_str = "IXFR, incoming";
	}

	/* Execute zone transfer. */
	int ret = zone_master_try(conf, zone, try_xfer, &data, err_str);
	zone_clear_preferred_master(zone);
	if (ret != KNOT_EOK) {
		log_zone_error(zone->name, "%s, failed (%s)", err_str,
		               knot_strerror(ret));
		if (is_bootstrap) {
			zone->bootstrap_retry = bootstrap_next(zone->bootstrap_retry);
			zone_events_schedule(zone, ZONE_EVENT_XFER, zone->bootstrap_retry);
		} else {
			const knot_rdataset_t *soa = zone_soa(zone);
			zone_events_schedule(zone, ZONE_EVENT_XFER, knot_soa_retry(soa));
			start_expire_timer(conf, zone, soa);
		}

		return KNOT_EOK;
	}

	assert(!zone_contents_is_empty(zone->contents));
	const knot_rdataset_t *soa = zone_soa(zone);

	/* Rechedule events. */
	zone_events_schedule(zone, ZONE_EVENT_REFRESH, knot_soa_refresh(soa));
	zone_events_schedule(zone, ZONE_EVENT_NOTIFY,  ZONE_EVENT_NOW);
	zone_events_cancel(zone, ZONE_EVENT_EXPIRE);
	conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name);
	int64_t sync_timeout = conf_int(&val);
	if (sync_timeout == 0) {
		zone_events_schedule(zone, ZONE_EVENT_FLUSH, ZONE_EVENT_NOW);
	} else if (sync_timeout > 0 &&
	           !zone_events_is_scheduled(zone, ZONE_EVENT_FLUSH)) {
		zone_events_schedule(zone, ZONE_EVENT_FLUSH, sync_timeout);
	}

	/* Transfer cleanup. */
	zone->bootstrap_retry = ZONE_EVENT_NOW;
	zone->flags &= ~ZONE_FORCE_AXFR;

	/* Trim extra heap. */
	if (!is_bootstrap) {
		mem_trim();
	}

	return KNOT_EOK;
}
예제 #19
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;
}
예제 #20
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;
}
예제 #21
0
파일: dbase.c 프로젝트: OpenSIPS/opensips
static int db_postgres_submit_async_query(const db_con_t* _con, const str* _s)
{
	int i,ret=0;
	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<max_db_queries;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,
						sql_slow_queries, sql_total_queries);
		/* exec the query */
		if (ret) {
			LM_DBG("%p PQsendQuery(%.*s)\n", _con, _s->len, _s->s);
			return 0;
		} else {
			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;
}
예제 #22
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;
}
예제 #23
0
파일: proto_wss.c 프로젝트: NormB/opensips
/*! \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;
}
예제 #24
0
/* ret= 0! if action -> end of list(e.g DROP), 
      > 0 to continue processing next actions
   and <0 on error */
int do_action(struct action* a, struct sip_msg* msg)
{
	int ret;
	int v;
	int sec,usec;
	union sockaddr_union* to;
	struct proxy_l* p;
	char* tmp;
	char *new_uri, *end, *crt;
	int len,i;
	int user = 0;
	int expires = 0;
	str vals[5];
	str result;
	struct sip_uri uri, next_hop;
	struct sip_uri *u;
	unsigned short port;
	int cmatch;
	struct action *aitem;
	struct action *adefault;
	pv_spec_t *spec;
	pv_elem_p model;
	pv_value_t val;
	pv_elem_t *pve;
	str name_s;
	struct timeval start;
	int end_time;
	action_elem_t *route_params_bak;
	int route_params_number_bak;

	/* reset the value of error to E_UNSPEC so avoid unknowledgable
	   functions to return with error (status<0) and not setting it
	   leaving there previous error; cache the previous value though
	   for functions which want to process it */
	prev_ser_error=ser_error;
	ser_error=E_UNSPEC;

	start_expire_timer(start,execmsgthreshold);

	ret=E_BUG;
	switch ((unsigned char)a->type){
		case DROP_T:
				script_trace("core", "drop", msg, a->line) ;
				action_flags |= ACT_FL_DROP;
		case EXIT_T:
				script_trace("core", "exit", msg, a->line) ;
				ret=0;
				action_flags |= ACT_FL_EXIT;
			break;
		case RETURN_T:
				script_trace("core", "return", msg, a->line) ;
				if (a->elem[0].type == SCRIPTVAR_ST)
				{
					spec = (pv_spec_t*)a->elem[0].u.data;
					if(pv_get_spec_value(msg, spec, &val)!=0
						|| (val.flags&PV_VAL_NULL))
					{
						ret=-1;
					} else {
						if(!(val.flags&PV_VAL_INT))
							ret = 1;
						else
							ret = val.ri;
					}
					pv_value_destroy(&val);
				} else {
					ret=a->elem[0].u.number;
				}
				action_flags |= ACT_FL_RETURN;
			break;
		case FORWARD_T:
			script_trace("core", "forward", msg, a->line) ;
			if (a->elem[0].type==NOSUBTYPE){
				/* parse uri and build a proxy */
				if (msg->dst_uri.len) {
					ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
						&next_hop);
					u = &next_hop;
				} else {
					ret = parse_sip_msg_uri(msg);
					u = &msg->parsed_uri;
				}
				if (ret<0) {
					LM_ERR("forward: bad_uri dropping packet\n");
					break;
				}
				/* create a temporary proxy*/
				p=mk_proxy(u->maddr_val.len?&u->maddr_val:&u->host,
					u->port_no, u->proto, (u->type==SIPS_URI_T)?1:0 );
				if (p==0){
					LM_ERR("bad host name in uri, dropping packet\n");
					ret=E_BAD_ADDRESS;
					goto error_fwd_uri;
				}
				ret=forward_request(msg, p);
				free_proxy(p); /* frees only p content, not p itself */
				pkg_free(p);
				if (ret==0) ret=1;
			}else if ((a->elem[0].type==PROXY_ST)) {
				ret=forward_request(msg,(struct proxy_l*)a->elem[0].u.data);
				if (ret==0) ret=1;
			}else{
				LM_ALERT("BUG in forward() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
			}
			break;
		case SEND_T:
			script_trace("core", "send", msg, a->line) ;
			if (a->elem[0].type!= PROXY_ST){
				LM_ALERT("BUG in send() type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if (a->elem[1].u.data) {
				if (a->elem[1].type != SCRIPTVAR_ELEM_ST){
					LM_ALERT("BUG in send() header type %d\n",a->elem[1].type);
					ret=E_BUG;
					break;
				} else {
					pve = (pv_elem_t *)a->elem[1].u.data;
				}
			} else {
				pve = NULL;
			}
			to=(union sockaddr_union*)
					pkg_malloc(sizeof(union sockaddr_union));
			if (to==0){
				LM_ERR("memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			
			p=(struct proxy_l*)a->elem[0].u.data;
			
			ret=hostent2su(to, &p->host, p->addr_idx,
						(p->port)?p->port:SIP_PORT );
			if (ret==0){
				if (pve) {
					if ( pv_printf_s(msg, pve, &name_s)!=0 || 
							name_s.len == 0 || name_s.s == NULL) {
						LM_WARN("cannot get string for value\n");
						ret=E_UNSPEC;
						break;
					}
					/* build new msg */
					tmp = pkg_malloc(msg->len + name_s.len);
					if (!tmp) {
						LM_ERR("memory allocation failure\n");
						ret = E_OUT_OF_MEM;
						break;
					}
					LM_DBG("searching for first line %d\n",
							msg->first_line.len);
					/* search first line of previous msg */
					/* copy headers */
					len = msg->first_line.len;
					memcpy(tmp, msg->buf, len);
					memcpy(tmp + len, name_s.s, name_s.len);
					memcpy(tmp + len + name_s.len,
							msg->buf + len, msg->len - len);
					ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/,
							tmp, msg->len + name_s.len);
					pkg_free(tmp);
				} else {
					ret = msg_send(0/*send_sock*/, p->proto, to, 0/*id*/,
							msg->buf, msg->len);
				}
				if (ret!=0 && p->host.h_addr_list[p->addr_idx+1])
					p->addr_idx++;
			}
			pkg_free(to);
			if (ret==0)
				ret=1;
			break;
		case LOG_T:
			script_trace("core", "log", msg, a->line) ;
			if ((a->elem[0].type!=NUMBER_ST)|(a->elem[1].type!=STRING_ST)){
				LM_ALERT("BUG in log() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
				break;
			}
			LM_GEN1(a->elem[0].u.number, "%s", a->elem[1].u.string);
			ret=1;
			break;
		case APPEND_BRANCH_T:
			script_trace("core", "append_branch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in append_branch %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[0].u.s.s==NULL) {
				ret = append_branch(msg, 0, &msg->dst_uri, &msg->path_vec,
					get_ruri_q(), getb0flags(), msg->force_send_socket);
				/* reset all branch info */
				msg->force_send_socket = 0;
				setb0flags(0);
				set_ruri_q(Q_UNSPECIFIED);
				if(msg->dst_uri.s!=0)
					pkg_free(msg->dst_uri.s);
				msg->dst_uri.s = 0;
				msg->dst_uri.len = 0;
				if(msg->path_vec.s!=0)
					pkg_free(msg->path_vec.s);
				msg->path_vec.s = 0;
				msg->path_vec.len = 0;
			} else {
				ret = append_branch(msg, &a->elem[0].u.s, &msg->dst_uri, 
					&msg->path_vec, a->elem[1].u.number, getb0flags(),
					msg->force_send_socket);
			}
			break;
		case REMOVE_BRANCH_T:
			script_trace("core", "remove_branch", msg, a->line) ;
			if (a->elem[0].type == SCRIPTVAR_ST) {
				spec = (pv_spec_t*)a->elem[0].u.data;
				if( pv_get_spec_value(msg, spec, &val)!=0
				|| (val.flags&PV_VAL_NULL) || !(val.flags&PV_VAL_INT) ) {
					ret=-1;
					break;
				}
				i = val.ri;
			} else {
				i=a->elem[0].u.number;
			}
			ret = (remove_branch((unsigned int)i)==0)?1:-1;
			break;
		case LEN_GT_T:
			script_trace("core", "len_gt", msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST) {
				LM_ALERT("BUG in len_gt type %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			ret = (msg->len >= (unsigned int)a->elem[0].u.number) ? 1 : -1;
			break;
		case SET_DEBUG_T:
			script_trace("core", "set_debug", msg, a->line) ;
			if (a->elem[0].type==NUMBER_ST)
				set_proc_debug_level(a->elem[0].u.number);
			else
				reset_proc_debug_level();
			ret = 1;
			break;
		case SETFLAG_T:
			script_trace("core", "setflag", msg, a->line) ;
			ret = setflag( msg, a->elem[0].u.number );
			break;
		case RESETFLAG_T:
			script_trace("core", "resetflag", msg, a->line) ;
			ret = resetflag( msg, a->elem[0].u.number );
			break;
		case ISFLAGSET_T:
			script_trace("core", "isflagset", msg, a->line) ;
			ret = isflagset( msg, a->elem[0].u.number );
			break;
		case SETSFLAG_T:
			script_trace("core", "setsflag", msg, a->line) ;
			ret = setsflag( a->elem[0].u.number );
			break;
		case RESETSFLAG_T:
			script_trace("core", "resetsflag", msg, a->line) ;
			ret = resetsflag( a->elem[0].u.number );
			break;
		case ISSFLAGSET_T:
			script_trace("core", "issflagset", msg, a->line) ;
			ret = issflagset( a->elem[0].u.number );
			break;
		case SETBFLAG_T:
			script_trace("core", "setbflag", msg, a->line) ;
			ret = setbflag( a->elem[0].u.number, a->elem[1].u.number );
			break;
		case RESETBFLAG_T:
			script_trace("core", "resetbflag", msg, a->line) ;
			ret = resetbflag( a->elem[0].u.number, a->elem[1].u.number  );
			break;
		case ISBFLAGSET_T:
			script_trace("core", "isbflagset", msg, a->line) ;
			ret = isbflagset( a->elem[0].u.number, a->elem[1].u.number  );
			break;
		case ERROR_T:
			script_trace("core", "error", msg, a->line) ;
			if ((a->elem[0].type!=STRING_ST)|(a->elem[1].type!=STRING_ST)){
				LM_ALERT("BUG in error() types %d, %d\n",
						a->elem[0].type, a->elem[1].type);
				ret=E_BUG;
				break;
			}
			LM_ERR("error(\"%s\", \"%s\") not implemented yet\n",
				a->elem[0].u.string, a->elem[1].u.string);
			ret=1;
			break;
		case ROUTE_T:
			script_trace("route", rlist[a->elem[0].u.number].name, msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST){
				LM_ALERT("BUG in route() type %d\n",
						a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if ((a->elem[0].u.number>RT_NO)||(a->elem[0].u.number<0)){
				LM_ALERT("BUG - invalid routing table number in"
							"route(%lu)\n", a->elem[0].u.number);
				ret=E_CFG;
				break;
			}
			/* check if the route has parameters */
			if (a->elem[1].type != 0) {
				if (a->elem[1].type != NUMBER_ST || a->elem[2].type != SCRIPTVAR_ELEM_ST) {
					LM_ALERT("BUG in route() type %d/%d\n",
							a->elem[1].type, a->elem[2].type);
					ret=E_BUG;
					break;
				}
				route_params_bak = route_params;
				route_params = (action_elem_t *)a->elem[2].u.data;
				route_params_number_bak = route_params_number;
				route_params_number = a->elem[1].u.number;

				return_code=run_actions(rlist[a->elem[0].u.number].a, msg);
				route_params = route_params_bak;
				route_params_number = route_params_number_bak;
			} else {
				return_code=run_actions(rlist[a->elem[0].u.number].a, msg);
			}
			ret=return_code;
			break;
		case REVERT_URI_T:
			script_trace("core", "revert_uri", msg, a->line) ;
			if (msg->new_uri.s) {
				pkg_free(msg->new_uri.s);
				msg->new_uri.len=0;
				msg->new_uri.s=0;
				msg->parsed_uri_ok=0; /* invalidate current parsed uri*/
			};
			ret=1;
			break;
		case SET_HOST_T:
		case SET_HOSTPORT_T:
		case SET_USER_T:
		case SET_USERPASS_T:
		case SET_PORT_T:
		case SET_URI_T:
		case PREFIX_T:
		case STRIP_T:
		case STRIP_TAIL_T:
				script_trace("core", 
					(unsigned char)a->type == SET_HOST_T     ? "set_host" :
					(unsigned char)a->type == SET_HOSTPORT_T ? "set_hostport" : 
					(unsigned char)a->type == SET_USER_T     ? "set_user" :
					(unsigned char)a->type == SET_USERPASS_T ? "set_userpass" : 
					(unsigned char)a->type == SET_PORT_T     ? "set_port" :
					(unsigned char)a->type == SET_URI_T      ? "set_uri" : 
					(unsigned char)a->type == PREFIX_T       ? "prefix" :
					(unsigned char)a->type == STRIP_T  ? "strip" : "strip_tail",
					msg, a->line);
				user=0;
				if (a->type==STRIP_T || a->type==STRIP_TAIL_T) {
					if (a->elem[0].type!=NUMBER_ST) {
						LM_ALERT("BUG in set*() type %d\n",
							a->elem[0].type);
						break;
					}
				} else if (a->elem[0].type!=STR_ST){
					LM_ALERT("BUG in set*() type %d\n",
							a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (a->type==SET_URI_T) {
					if (set_ruri( msg, &a->elem[0].u.s) ) {
						LM_ERR("failed to set new RURI\n");
						ret=E_OUT_OF_MEM;
						break;
					}
					ret=1;
					break;
				}
				if (msg->new_uri.s) {
					tmp=msg->new_uri.s;
					len=msg->new_uri.len;
				}else{
					tmp=msg->first_line.u.request.uri.s;
					len=msg->first_line.u.request.uri.len;
				}
				if (parse_uri(tmp, len, &uri)<0){
					LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp);
					ret=E_UNSPEC;
					break;
				}
				
				new_uri=pkg_malloc(MAX_URI_SIZE);
				if (new_uri==0){
					LM_ERR("memory allocation failure\n");
					ret=E_OUT_OF_MEM;
					break;
				}
				end=new_uri+MAX_URI_SIZE;
				crt=new_uri;
				/* begin copying */
				len = (uri.user.len?uri.user.s:uri.host.s) - tmp;
				if (crt+len>end) goto error_uri;
				memcpy(crt,tmp,len);crt+=len;

				if (a->type==PREFIX_T) {
					if (crt+a->elem[0].u.s.len>end) goto error_uri;
					memcpy( crt, a->elem[0].u.s.s, a->elem[0].u.s.len);
					crt+=a->elem[0].u.s.len;
					/* whatever we had before, with prefix we have username 
					   now */
					user=1;
				}

				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else if (a->type==STRIP_T) {
					if (a->elem[0].u.number>uri.user.len) {
						LM_WARN("too long strip asked; "
								" deleting username: %lu of <%.*s>\n",
								a->elem[0].u.number, uri.user.len, uri.user.s);
						len=0;
					} else if (a->elem[0].u.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s + a->elem[0].u.number;
						len=uri.user.len - a->elem[0].u.number;
					}
				} else if (a->type==STRIP_TAIL_T) {
					if (a->elem[0].u.number>uri.user.len) {
						LM_WARN("too long strip_tail asked;"
								" deleting username: %lu of <%.*s>\n",
								a->elem[0].u.number, uri.user.len, uri.user.s);
						len=0;
					} else if (a->elem[0].u.number==uri.user.len) {
						len=0;
					} else {
						tmp=uri.user.s;
						len=uri.user.len - a->elem[0].u.number;
					}
				} else {
					tmp=uri.user.s;
					len=uri.user.len;
				}

				if (len){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
					user=1; /* we have an user field so mark it */
				}

				if (a->type==SET_USERPASS_T) tmp=0;
				else tmp=uri.passwd.s;
				/* passwd */
				if (tmp){
					len=uri.passwd.len; if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* host */
				if (user || tmp){ /* add @ */
					if(crt+1>end) goto error_uri;
					*crt='@'; crt++;
				}
				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else {
					tmp=uri.host.s;
					len = uri.host.len;
				}
				if (tmp){
					if(crt+len>end) goto error_uri;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* port */
				if (a->type==SET_HOSTPORT_T) tmp=0;
				else if (a->type==SET_PORT_T) {
					tmp=a->elem[0].u.s.s;
					len=a->elem[0].u.s.len;
				} else {
					tmp=uri.port.s;
					len = uri.port.len;
				}
				if (tmp && len>0){
					if(crt+len+1>end) goto error_uri;
					*crt=':'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				/* params */
				tmp=uri.params.s;
				if (tmp){
					/* include in param string the starting ';' */
					len=uri.params.len+1;
					tmp--;
					if(crt+len+1>end) goto error_uri;
					/* if a maddr param is present, strip it out */
					if (uri.maddr.len &&
					(a->type==SET_HOSTPORT_T || a->type==SET_HOST_T)) {
						memcpy(crt,tmp,uri.maddr.s-tmp-1);
						crt+=uri.maddr.s-tmp-1;
						memcpy(crt,uri.maddr_val.s+uri.maddr_val.len,
							tmp+len-uri.maddr_val.s-uri.maddr_val.len);
						crt+=tmp+len-uri.maddr_val.s-uri.maddr_val.len;
					} else {
						memcpy(crt,tmp,len);crt+=len;
					}
				}
				/* headers */
				tmp=uri.headers.s;
				if (tmp){
					len=uri.headers.len; if(crt+len+1>end) goto error_uri;
					*crt='?'; crt++;
					memcpy(crt,tmp,len);crt+=len;
				}
				*crt=0; /* null terminate the thing */
				/* copy it to the msg */
				if (msg->new_uri.s) pkg_free(msg->new_uri.s);
				msg->new_uri.s=new_uri;
				msg->new_uri.len=crt-new_uri;
				msg->parsed_uri_ok=0;
				ret=1;
				break;
		case SET_DSTURI_T:
			script_trace("core", "set_dsturi", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in setdsturi() type %d\n",
							a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if(set_dst_uri(msg, &a->elem[0].u.s)!=0)
				ret = -1;
			else
				ret = 1;
			break;
		case SET_DSTHOST_T:
		case SET_DSTPORT_T:
			script_trace("core", (unsigned char) a->type == SET_DSTHOST_T ?
						 "set_dsturi" : "set_dstport", msg, a->line);
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in domain setting type %d\n",
							a->elem[0].type);
				ret=E_BUG;
				break;
			}

			tmp = msg->dst_uri.s;
			len = msg->dst_uri.len;

			if (tmp == NULL || len == 0) {
				LM_ERR("failure - null uri\n");
				ret = E_UNSPEC;
				break;
			}
			if (a->type == SET_DSTHOST_T &&
					(a->elem[0].u.s.s == NULL || a->elem[0].u.s.len == 0)) {
				LM_ERR("cannot set a null uri domain\n");
				break;
			}
			if (parse_uri(tmp, len, &uri)<0) {
				LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp);
				break;
			}
			new_uri=pkg_malloc(MAX_URI_SIZE);
			if (new_uri == NULL) {
				LM_ERR("memory allocation failure\n");
				ret=E_OUT_OF_MEM;
				break;
			}
			end=new_uri+MAX_URI_SIZE;
			crt=new_uri;
			len = (uri.user.len?uri.user.s:uri.host.s) - tmp;
			if (crt+len>end) goto error_uri;
			memcpy(crt,tmp,len);
			crt += len;
			/* user */
			tmp = uri.user.s;
			len = uri.user.len;
			if (tmp) {
				if (crt+len>end) goto error_uri;
				memcpy(crt,tmp,len);
				crt += len;
				user = 1;
			}
			/* passwd */
			tmp = uri.passwd.s;
			len = uri.passwd.len;
			if (user || tmp) {
				if (crt+len+1>end) goto error_uri;
				*crt++=':';
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* host */
			if (a->type==SET_DSTHOST_T) {
				tmp = a->elem[0].u.s.s;
				len = a->elem[0].u.s.len;
			} else {
				tmp = uri.host.s;
				len = uri.host.len;
			}
			if (tmp) {
				if (user) {
					if (crt+1>end) goto error_uri;
					*crt++='@';
				}
				if (crt+len+1>end) goto error_uri;
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* port */
			if (a->type==SET_DSTPORT_T) {
				tmp = a->elem[0].u.s.s;
				len = a->elem[0].u.s.len;
			} else {
				tmp = uri.port.s;
				len = uri.port.len;
			}
			if (tmp) {
				if (crt+len+1>end) goto error_uri;
				*crt++=':';
				memcpy(crt, tmp, len);
				crt += len;
			}
			/* params */
			tmp=uri.params.s;
			if (tmp){
				len=uri.params.len; if(crt+len+1>end) goto error_uri;
				*crt++=';';
				memcpy(crt,tmp,len);
				crt += len;
			}
			/* headers */
			tmp=uri.headers.s;
			if (tmp){
				len=uri.headers.len; if(crt+len+1>end) goto error_uri;
				*crt++='?';
				memcpy(crt,tmp,len);
				crt += len;
			}
			*crt=0; /* null terminate the thing */
			/* copy it to the msg */
			pkg_free(msg->dst_uri.s);
			msg->dst_uri.s=new_uri;
			msg->dst_uri.len=crt-new_uri;
			ret = 1;
			break;
		case RESET_DSTURI_T:
			script_trace("core", "reset_dsturi", msg, a->line) ;
			if(msg->dst_uri.s!=0)
				pkg_free(msg->dst_uri.s);
			msg->dst_uri.s = 0;
			msg->dst_uri.len = 0;
			ret = 1;
			break;
		case ISDSTURISET_T:
			script_trace("core", "isdsturiset", msg, a->line) ;
			if(msg->dst_uri.s==0 || msg->dst_uri.len<=0)
				ret = -1;
			else
				ret = 1;
			break;
		case IF_T:
			script_trace("core", "if", msg, a->line) ;
				/* if null expr => ignore if? */
				if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){
					v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0);
					/* set return code to expr value */
					if (v<0 || (action_flags&ACT_FL_RETURN)
							|| (action_flags&ACT_FL_EXIT) ){
						if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){ /* hack to quit on DROP*/
							ret=0;
							return_code = 0;
							break;
						}else{
							LM_WARN("error in expression (l=%d)\n", a->line);
						}
					}
					
					ret=1;  /*default is continue */
					if (v>0) {
						if ((a->elem[1].type==ACTIONS_ST)&&a->elem[1].u.data){
							ret=run_action_list(
									(struct action*)a->elem[1].u.data,msg );
							return_code = ret;
						} else return_code = v;
					}else{
						if ((a->elem[2].type==ACTIONS_ST)&&a->elem[2].u.data){
							ret=run_action_list(
								(struct action*)a->elem[2].u.data,msg);
							return_code = ret;
						} else return_code = v;
					}
				}
			break;
		case WHILE_T:
			script_trace("core", "while", msg, a->line) ;
				/* if null expr => ignore if? */
				if ((a->elem[0].type==EXPR_ST)&&a->elem[0].u.data){
					len = 0;
					while(1)
					{
						if(len++ >= max_while_loops)
						{
							LM_INFO("max while loops are encountered\n");
							break;
						}
						v=eval_expr((struct expr*)a->elem[0].u.data, msg, 0);
						/* set return code to expr value */
						if (v<0 || (action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){
							if (v==EXPR_DROP || (action_flags&ACT_FL_RETURN)
									|| (action_flags&ACT_FL_EXIT) ){
								ret=0;
								return_code = 0;
								break;
							}else{
								LM_WARN("error in expression (l=%d)\n",
										a->line);
							}
						}
					
						ret=1;  /*default is continue */
						if (v>0) {
							if ((a->elem[1].type==ACTIONS_ST)
									&&a->elem[1].u.data){
								ret=run_action_list(
									(struct action*)a->elem[1].u.data,msg );
								/* check if return was done */
								if ((action_flags&ACT_FL_RETURN)
								|| (action_flags&ACT_FL_EXIT) ){
									break;
								}
								return_code = ret;
							} else {
								/* we should not get here */
								return_code = v;
								break;
							}
						} else {
							/* condition was false */
							return_code = v;
							break;
						}
					}
				}
			break;
		case CACHE_STORE_T:
			script_trace("core", "cache_store", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[2].type!=STR_ST)) {
				LM_ALERT("BUG in cache_store() - third argument not of type"
						" string%d\n", a->elem[2].type );
				ret=E_BUG;
				break;
			}

			str val_s;

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			/* parse the value argument */
			pve = (pv_elem_t *)a->elem[2].u.data;
			if ( pv_printf_s(msg, pve, &val_s)!=0 || 
			val_s.len == 0 || val_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			/* get the expires value */
			if ( a->elem[3].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[3].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_store\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_store expires, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				expires = val.ri;
			}
			else
			if ( a->elem[3].type == NUMBER_ST )
			{
				expires = (int)a->elem[3].u.number;
			}

			ret = cachedb_store( &a->elem[0].u.s, &name_s, &val_s,expires);

			break;
		case CACHE_REMOVE_T:
			script_trace("core", "cache_remove", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_remove() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_remove() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}
			ret = cachedb_remove( &a->elem[0].u.s, &name_s);
			break;
		case CACHE_FETCH_T:
			script_trace("core", "cache_fetch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in cache_fetch() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			str aux = {0, 0};
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			ret = cachedb_fetch( &a->elem[0].u.s, &name_s, &aux);
			if(ret > 0)
			{
				val.rs = aux;
				val.flags = PV_VAL_STR;

				spec = (pv_spec_t*)a->elem[2].u.data;
				if (pv_set_value(msg, spec, 0, &val) < 0) {
					LM_ERR("cannot set the variable value\n");
					pkg_free(aux.s);
					return -1;
				}
				pkg_free(aux.s);
			}
			
			break;
		case CACHE_COUNTER_FETCH_T:
			script_trace("core", "cache_counter_fetch", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in cache_fetch() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			int aux_counter;
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			ret = cachedb_counter_fetch( &a->elem[0].u.s, &name_s, &aux_counter);
			if(ret > 0)
			{
				val.ri = aux_counter;
				val.flags = PV_TYPE_INT|PV_VAL_INT;

				spec = (pv_spec_t*)a->elem[2].u.data;
				if (pv_set_value(msg, spec, 0, &val) < 0) {
					LM_ERR("cannot set the variable value\n");
					pkg_free(aux.s);
					return -1;
				}
			}
			break;
		case CACHE_ADD_T:
			script_trace("core", "cache_add", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_add() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_add()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			int increment=0;

			/* get the increment value */
			if ( a->elem[2].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[2].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_add\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_add, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				increment = val.ri;
			}
			else if ( a->elem[2].type == NUMBER_ST )
			{
				increment = (int)a->elem[2].u.number;
			}

			expires = (int)a->elem[3].u.number;

			/* TODO - return the new value to script ? */
			ret = cachedb_add(&a->elem[0].u.s, &name_s, increment,expires,NULL);
			break;
		case CACHE_SUB_T:
			script_trace("core", "cache_sub", msg, a->line) ;
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_sub() - first argument not of"
						" type string [%d]\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}

			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_sub()  - second argument not of "
						"type string [%d]\n", a->elem[1].type );
				ret=E_BUG;
				break;
			}

			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			int decrement=0;

			/* get the increment value */
			if ( a->elem[2].type == SCRIPTVAR_ST )
			{
				spec = (pv_spec_t*)a->elem[2].u.data;
				memset(&val, 0, sizeof(pv_value_t));
				if(pv_get_spec_value(msg, spec, &val) < 0)
				{
					LM_DBG("Failed to get scriptvar value while executing cache_sub\n");
					ret=E_BUG;
					break;
				}
				if (!(val.flags&PV_VAL_INT))
				{
					LM_ERR("Wrong value for cache_sub, not an integer [%.*s]\n",
							val.rs.len, val.rs.s);
				}
				decrement = val.ri;
			}
			else if ( a->elem[2].type == NUMBER_ST )
			{
				decrement = (int)a->elem[2].u.number;
			}

			expires = (int)a->elem[3].u.number;

			/* TODO - return new value to script ? */
			ret = cachedb_sub(&a->elem[0].u.s, &name_s, decrement,expires,NULL);
			break;
		case CACHE_RAW_QUERY_T:
			if ((a->elem[0].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[0].type );
				ret=E_BUG;
				break;
			}
			if ((a->elem[1].type!=STR_ST)) {
				LM_ALERT("BUG in cache_fetch() %d\n",
					a->elem[1].type );
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data != NULL && 
				a->elem[2].type!=STR_ST){
				LM_ALERT("BUG in cache_raw_query() type %d\n",
						a->elem[2].type);
				ret=E_BUG;
				break;
			}
			/* parse the name argument */
			pve = (pv_elem_t *)a->elem[1].u.data;
			if ( pv_printf_s(msg, pve, &name_s)!=0 || 
			name_s.len == 0 || name_s.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}

			cdb_raw_entry **cdb_reply;
			int val_number=0,i,j;
			int key_number=0;
			pvname_list_t *cdb_res,*it;
			int_str avp_val;
			int_str avp_name;
			unsigned short avp_type;

			if (a->elem[2].u.data) {
				cdb_res = (pvname_list_t*)a->elem[2].u.data;
				for (it=cdb_res;it;it=it->next)
					val_number++;

				LM_DBG("The query expects %d results back\n",val_number);

				ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, &cdb_reply,val_number,&key_number);
				if (ret >= 0 && val_number > 0) {
					for (i=key_number-1; i>=0;i--) {
						it=cdb_res;
						for (j=0;j < val_number;j++) {
							avp_type = 0;
							if (pv_get_avp_name(msg,&it->sname.pvp,&avp_name.n,
								&avp_type) != 0) {
								LM_ERR("cannot get avp name [%d/%d]\n",i,j);
								goto next_avp;
							}
							
							switch (cdb_reply[i][j].type) {
								case CDB_INT:
									avp_val.n = cdb_reply[i][j].val.n; 
									break;
								case CDB_STR:
									avp_type |= AVP_VAL_STR;
									avp_val.s = cdb_reply[i][j].val.s;
									break;
								default:
									LM_WARN("Unknown type %d\n",cdb_reply[i][j].type);
									goto next_avp;
							}
							if (add_avp(avp_type,avp_name.n,avp_val) != 0) {
								LM_ERR("Unable to add AVP\n");
								free_raw_fetch(cdb_reply,val_number,key_number);
								return -1;
							}
next_avp:
							if (it) {
								it = it->next;
								if (it==NULL);
									break;
							}
						}
					}
					free_raw_fetch(cdb_reply,val_number,key_number);
				}
			}
			else
				ret = cachedb_raw_query( &a->elem[0].u.s, &name_s, NULL,0,NULL);
			break;
		case XDBG_T:
			script_trace("core", "xdbg", msg, a->line) ;
			if (a->elem[0].type == SCRIPTVAR_ELEM_ST)
			{
				if (xdbg(msg, a->elem[0].u.data, val.rs.s) < 0)
				{
					LM_ALERT("Cannot print message");
					break;
				}
			}
			else
			{
				LM_ALERT("BUG in xdbg() type %d\n", a->elem[0].type);
				ret=E_BUG;
			}
			break;
		case XLOG_T:
			script_trace("core", "xlog", msg, a->line) ;
			if (a->elem[1].u.data != NULL)
			{
				if (a->elem[1].type != SCRIPTVAR_ELEM_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[1].type);
					ret=E_BUG;
					break;
				}
				if (a->elem[0].type != STR_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (xlog_2(msg,a->elem[0].u.data, a->elem[1].u.data) < 0)
				{
					LM_ALERT("Cannot print xlog debug message");
					break;
				}
			}
			else
			{
				if (a->elem[0].type != SCRIPTVAR_ELEM_ST)
				{
					LM_ALERT("BUG in xlog() type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
				if (xlog_1(msg,a->elem[0].u.data, val.rs.s) < 0)
				{
					LM_ALERT("Cannot print xlog debug message");
					break;
				}
			}

			break;
		case RAISE_EVENT_T:
			script_trace("core", "raise_event", msg, a->line) ;
			if (a->elem[0].type != NUMBER_ST) {
				LM_ERR("invalid event id\n");
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data) {
				/* three parameters specified */
				ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number,
						a->elem[1].u.data, a->elem[2].u.data);
			} else {
				/* two parameters specified */
				ret = evi_raise_script_event(msg, (event_id_t)a->elem[0].u.number,
						NULL, a->elem[1].u.data);
			}
			if (ret <= 0) {
				LM_ERR("cannot raise event\n");
				ret=E_UNSPEC;
				break;
			}
			break;
		case SUBSCRIBE_EVENT_T:
			script_trace("core", "subscribe_event", msg, a->line) ;
			if (a->elem[0].type != STR_ST || a->elem[1].type != STR_ST) {
				LM_ERR("BUG in subscribe arguments\n");
				ret=E_BUG;
				break;
			}
			if (a->elem[2].u.data) {
				if (a->elem[2].type != NUMBER_ST) {
					LM_ERR("BUG in subscribe expiration time\n");
					ret=E_BUG;
					break;
				} else {
					i = a->elem[2].u.number;
				}
			} else {
				i = 0;
			}

			name_s.s = a->elem[0].u.data;
			name_s.len = strlen(name_s.s);
			/* result should be the socket */
			result.s = a->elem[1].u.data;
			result.len = strlen(result.s);
			ret = evi_event_subscribe(name_s, result, i, 0);
			break;

		case CONSTRUCT_URI_T:
			script_trace("core", "construct_uri", msg, a->line) ;
			for (i=0;i<5;i++)
			{
				pve = (pv_elem_t *)a->elem[i].u.data;
				if (pve->spec.getf)
				{
					if ( pv_printf_s(msg, pve, &vals[i])!=0 || 
						vals[i].len == 0 || vals[i].s == NULL) 
					{
						LM_WARN("cannot get string for value\n");
						ret=E_BUG;
						return -1;
					}
				}
				else
					vals[i] = pve->text;
			}
			
			result.s = construct_uri(&vals[0],&vals[1],&vals[2],&vals[3],&vals[4],
					&result.len);

			if (result.s)
			{
				int_str res;
				int avp_name;
				unsigned short avp_type;

				spec = (pv_spec_t*)a->elem[5].u.data;
				if (pv_get_avp_name( msg, &(spec->pvp), &avp_name,
						&avp_type)!=0){
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.s = result;
				if (add_avp(AVP_VAL_STR|avp_type, avp_name, res)<0){
					LM_ERR("cannot add AVP\n");
					return -1;
				}
			}

			break;
		case GET_TIMESTAMP_T:
			script_trace("core", "get_timestamp", msg, a->line) ;
			if (get_timestamp(&sec,&usec) == 0) {
				int avp_name;
				int_str res;
				unsigned short avp_type;

				spec = (pv_spec_t*)a->elem[0].u.data;
				if (pv_get_avp_name(msg, &(spec->pvp), &avp_name,
						&avp_type) != 0) {
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.n = sec;
				if (add_avp(avp_type, avp_name, res) < 0) {
					LM_ERR("cannot add AVP\n");
					return -1;
				}

				spec = (pv_spec_t*)a->elem[1].u.data;
				if (pv_get_avp_name(msg, &(spec->pvp), &avp_name,
						&avp_type) != 0) {
					LM_CRIT("BUG in getting AVP name\n");
					return -1;
				}

				res.n = usec;
				if (add_avp(avp_type, avp_name, res) < 0) {
					LM_ERR("cannot add AVP\n");
					return -1;
				}
			} else {
				LM_ERR("failed to get time\n");
				return -1;
			}
			break;
		case SWITCH_T:
			script_trace("core", "switch", msg, a->line) ;
			if (a->elem[0].type!=SCRIPTVAR_ST){
				LM_ALERT("BUG in switch() type %d\n",
						a->elem[0].type);
				ret=E_BUG;
				break;
			}
			spec = (pv_spec_t*)a->elem[0].u.data;
			if(pv_get_spec_value(msg, spec, &val)!=0)
			{
				LM_ALERT("BUG - no value in switch()\n");
				ret=E_BUG;
				break;
			}

			/* get the value of pvar */
			if(a->elem[1].type!=ACTIONS_ST) {
				LM_ALERT("BUG in switch() actions\n");
				ret=E_BUG;
				break;
			}
			return_code=1;
			adefault = NULL;
			aitem = (struct action*)a->elem[1].u.data;
			cmatch=0;
			while(aitem)
			{
				if((unsigned char)aitem->type==DEFAULT_T)
					adefault=aitem;
				if(cmatch==0)
				{
					if(aitem->elem[0].type==STR_ST)
					{
						if(val.flags&PV_VAL_STR
								&& val.rs.len==aitem->elem[0].u.s.len
								&& strncasecmp(val.rs.s, aitem->elem[0].u.s.s,
									val.rs.len)==0)
							cmatch = 1;
					} else { /* number */
						if(val.flags&PV_VAL_INT && 
								val.ri==aitem->elem[0].u.number)
							cmatch = 1;
					}
				}
				if(cmatch==1)
				{
					if(aitem->elem[1].u.data)
					{
						return_code=run_action_list(
							(struct action*)aitem->elem[1].u.data, msg);
						if ((action_flags&ACT_FL_RETURN) ||
						(action_flags&ACT_FL_EXIT))
							break;
					}
					if(aitem->elem[2].u.number==1)
						break;
				}
				aitem = aitem->next;
			}
			if((cmatch==0) && (adefault!=NULL))
			{
				LM_DBG("switch: running default statement\n");
				if(adefault->elem[0].u.data)
					return_code=run_action_list(
						(struct action*)adefault->elem[0].u.data, msg);
			}
			ret=return_code;
			break;
		case MODULE_T:
			script_trace("module", ((cmd_export_t*)(a->elem[0].u.data))->name,
				msg, a->line) ;
			if ( (a->elem[0].type==CMD_ST) && a->elem[0].u.data ) {
				ret=((cmd_export_t*)(a->elem[0].u.data))->function(msg,
						 (char*)a->elem[1].u.data, (char*)a->elem[2].u.data,
						 (char*)a->elem[3].u.data, (char*)a->elem[4].u.data,
						 (char*)a->elem[5].u.data, (char*)a->elem[6].u.data);
			}else{
				LM_ALERT("BUG in module call\n");
			}
			break;
		case FORCE_RPORT_T:
			script_trace("core", "force_rport", msg, a->line) ;
			msg->msg_flags|=FL_FORCE_RPORT;
			ret=1; /* continue processing */
			break;
		case FORCE_LOCAL_RPORT_T:
			script_trace("core", "force_local_rport", msg, a->line) ;
			msg->msg_flags|=FL_FORCE_LOCAL_RPORT;
			ret=1; /* continue processing */
			break;
		case SET_ADV_ADDR_T:
			script_trace("core", "set_adv_addr", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in set_advertised_address() "
						"type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			str adv_addr;
			pve = (pv_elem_t *)a->elem[0].u.data;
			if ( pv_printf_s(msg, pve, &adv_addr)!=0 || 
			adv_addr.len == 0 || adv_addr.s == NULL) {
				LM_WARN("cannot get string for value\n");
				ret=E_BUG;
				break;
			}
			LM_DBG("adv address = [%.*s]\n",adv_addr.len,adv_addr.s);
			msg->set_global_address=adv_addr;
			ret=1; /* continue processing */
			break;
		case SET_ADV_PORT_T:
			script_trace("core", "set_adv_port", msg, a->line) ;
			if (a->elem[0].type!=STR_ST){
				LM_ALERT("BUG in set_advertised_port() "
						"type %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}

			msg->set_global_port=*((str*)a->elem[0].u.data);
			ret=1; /* continue processing */
			break;
#ifdef USE_TCP
		case FORCE_TCP_ALIAS_T:
			script_trace("core", "force_tcp_alias", msg, a->line) ;
			if ( msg->rcv.proto==PROTO_TCP
#ifdef USE_TLS
					|| msg->rcv.proto==PROTO_TLS
#endif
			   ){
				
				if (a->elem[0].type==NOSUBTYPE)	port=msg->via1->port;
				else if (a->elem[0].type==NUMBER_ST)
					port=(int)a->elem[0].u.number;
				else{
					LM_ALERT("BUG in force_tcp_alias"
							" port type %d\n", a->elem[0].type);
					ret=E_BUG;
					break;
				}
						
				if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
									msg->rcv.proto)!=0){
					LM_ERR("tcp alias failed\n");
					ret=E_UNSPEC;
					break;
				}
			}
#endif
			ret=1; /* continue processing */
			break;
		case FORCE_SEND_SOCKET_T:
			script_trace("core", "force_send_socket", msg, a->line) ;
			if (a->elem[0].type!=SOCKETINFO_ST){
				LM_ALERT("BUG in force_send_socket argument"
						" type: %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			msg->force_send_socket=(struct socket_info*)a->elem[0].u.data;
			ret=1; /* continue processing */
			break;
		case SERIALIZE_BRANCHES_T:
			script_trace("core", "serialize_branches", msg, a->line) ;
			if (a->elem[0].type!=NUMBER_ST){
				LM_ALERT("BUG in serialize_branches argument"
						" type: %d\n", a->elem[0].type);
				ret=E_BUG;
				break;
			}
			if (serialize_branches(msg,(int)a->elem[0].u.number)!=0) {
				LM_ERR("serialize_branches failed\n");
				ret=E_UNSPEC;
				break;
			}
			ret=1; /* continue processing */
			break;
		case NEXT_BRANCHES_T:
			script_trace("core", "next_branches", msg, a->line) ;
			if ((ret=next_branches(msg))<0) {
				LM_ERR("next_branches failed\n");
				ret=E_UNSPEC;
				break;
			}
			/* continue processing */
			break;
		case EQ_T:
		case COLONEQ_T:
		case PLUSEQ_T:
		case MINUSEQ_T:
		case DIVEQ_T:
		case MULTEQ_T:
		case MODULOEQ_T:
		case BANDEQ_T:
		case BOREQ_T:
		case BXOREQ_T:
			ret = do_assign(msg, a);
			break;
		case USE_BLACKLIST_T:
			script_trace("core", "use_blacklist", msg, a->line) ;
			mark_for_search((struct bl_head*)a->elem[0].u.data, 1);
			break;
		case UNUSE_BLACKLIST_T:
			script_trace("core", "unuse_blacklist", msg, a->line);
			mark_for_search((struct bl_head*)a->elem[0].u.data, 0);
			break;
		case PV_PRINTF_T:
			script_trace("core", "pv_printf", msg, a->line);
			ret = -1;
			spec = (pv_spec_p)a->elem[0].u.data;
			if(!pv_is_w(spec))
			{
				LM_ERR("read only PV in first parameter of pv_printf\n");
				goto error;
			}

			model = (pv_elem_p)a->elem[1].u.data;

			memset(&val, 0, sizeof(pv_value_t));
			if(pv_printf_s(msg, model, &val.rs)!=0)
			{
				LM_ERR("cannot eval second parameter\n");
				goto error;
			}
			val.flags = PV_VAL_STR;
			if(pv_set_value(msg, spec, EQ_T, &val)<0)
			{
				LM_ERR("setting PV failed\n");
				goto error;
			}
			
			ret = 1;
			break;
		case SCRIPT_TRACE_T:
			script_trace("core", "script_trace", msg, a->line);
			if (a->elem[0].type==NOSUBTYPE) {
				use_script_trace = 0;
			} else {
				
				use_script_trace = 1;
				
				if (a->elem[0].type != NUMBER_ST ||
					a->elem[1].type != SCRIPTVAR_ELEM_ST) {

					LM_ERR("BUG in use_script_trace() arguments\n");
					ret=E_BUG;
					break;
				}

				if (a->elem[2].type!=NOSUBTYPE) {
					script_trace_info = (char *)a->elem[2].u.data;
				} else {
					script_trace_info = NULL;
				}

				script_trace_log_level = (int)a->elem[0].u.number;
				script_trace_elem = *(pv_elem_p)a->elem[1].u.data;
			}

			break;
		default:
			LM_ALERT("BUG - unknown type %d\n", a->type);
			goto error;
	}

	if((unsigned char)a->type!=IF_T && (unsigned char)a->type!=ROUTE_T)
		return_code = ret;
/*skip:*/

	update_longest_action();
	return ret;

error:
	LM_ERR("error at line: %d\n", a->line);
	update_longest_action();
	return ret;
	
error_uri:
	LM_ERR("set*: uri too long\n");
	if (new_uri) pkg_free(new_uri);
	update_longest_action();
	return E_UNSPEC;
error_fwd_uri:
	update_longest_action();
	return ret;
}
예제 #25
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;
}
예제 #26
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;
}
예제 #27
0
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;
}