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; }
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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
/*! \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; }
/*! \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; }
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; }
/*! \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; }
/*! \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; }
/* 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; }
/*! \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; }
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; }
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; }