void b2bl_print_tuple(b2bl_tuple_t* tuple, int log_level) { int index; b2bl_entity_id_t* e; if(tuple) { LM_GEN1(log_level, "[%p]->[%.*s] to_del=[%d] lifetime=[%d]" " bridge_entities[%p][%p][%p]\n", tuple, tuple->key->len, tuple->key->s, tuple->to_del, tuple->lifetime, tuple->bridge_entities[0], tuple->bridge_entities[1], tuple->bridge_entities[2]); for (index = 0; index < MAX_B2BL_ENT; index++) { e = tuple->servers[index]; if (e) _print_entity(index, e, log_level); } for (index = 0; index < MAX_B2BL_ENT; index++) { e = tuple->clients[index]; if (e) _print_entity(index, e, log_level); } for (index = 0; index < MAX_BRIDGE_ENT; index++) { e = tuple->bridge_entities[index]; if (e) LM_GEN1(log_level, ".type=[%d] index=[%d] [%p]" " peer=[%p] prev:next=[%p][%p]\n", e->type, index, e, e->peer, e->prev, e->next); } } }
/** * Clean up on exit. This should be called before exiting. * \param show_status set to one to display the mem status */ void cleanup(int show_status) { LM_INFO("cleanup\n"); /*clean-up*/ /* hack: force-unlock the shared memory lock in case some process crashed and let it locked; this will allow an almost gracious shutdown */ if (mem_lock) #ifdef HP_MALLOC { int i; for (i = 0; i < HP_HASH_SIZE; i++) shm_unlock(i); } #else shm_unlock(); #endif handle_ql_shutdown(); destroy_modules(); #ifdef USE_TCP destroy_tcp(); #endif #ifdef USE_TLS destroy_tls(); #endif destroy_timer(); destroy_stats_collector(); destroy_script_cb(); pv_free_extra_list(); destroy_argv_list(); destroy_black_lists(); #ifdef PKG_MALLOC if (show_status){ LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); } #endif #ifdef SHM_MEM cleanup_debug(); if (pt) shm_free(pt); pt=0; if (show_status){ LM_GEN1(memdump, "Memory status (shm):\n"); shm_status(); } /* zero all shmem alloc vars that we still use */ shm_mem_destroy(); #endif if (pid_file) unlink(pid_file); if (pgid_file) unlink(pgid_file); }
void fm_free(struct fm_block* qm, void* p) #endif { struct fm_frag* f,*n; #ifdef DBG_MALLOC LM_GEN1(memlog, "%s_free(%p), called from %s: %s(%d)\n", qm->name, p, file, func, line); if (p && (p > (void *)qm->last_frag || p < (void *)qm->first_frag)) { LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); abort(); } #endif if (p==0) { LM_GEN1(memlog, "free(0) called\n"); return; } f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag)); #ifdef DBG_MALLOC LM_GEN1(memlog, "freeing block alloc'ed from %s: %s(%ld)\n", f->file, f->func, f->line); #endif join: if( qm->large_limit < qm->large_space ) goto no_join; n = FRAG_NEXT(f); if (((char*)n < (char*)qm->last_frag) && n->prev ) { fm_remove_free(qm, n); /* join */ f->size += n->size + FRAG_OVERHEAD; #if defined(DBG_MALLOC) || defined(STATISTICS) //qm->real_used -= FRAG_OVERHEAD; qm->used += FRAG_OVERHEAD; #endif goto join; } no_join: fm_insert_free(qm, f); #if defined(DBG_MALLOC) || defined(STATISTICS) qm->fragments -= 1; #endif pkg_threshold_check(); }
void dump_frag( struct vqm_frag* f, int i ) { LM_GEN1(memdump, " %3d. address=%p real size=%d bucket=%d\n", i, (char*)f+sizeof(struct vqm_frag), f->size, f->u.inuse.bucket); #ifdef DBG_QM_MALLOC LM_GEN1(memdump, " demanded size=%d\n", f->demanded_size ); LM_GEN1(memdump, " alloc'd from %s: %s(%d)\n", f->file, f->func, f->line); LM_GEN1(memdump, " start check=%x, end check= %.*s\n", f->check, END_CHECK_PATTERN_LEN, f->end_check ); #endif }
/** * Exit regulary on a specific signal. * This is good for profiling which only works if exited regularly * and not by default signal handlers * \param signo The signal that should be handled */ static void sig_usr(int signo) { int status; pid_t pid; UNUSED(pid); if (is_main){ if (sig_flag==0) sig_flag=signo; else /* previous sig. not processed yet, ignoring? */ return; ; if (dont_fork) /* only one proc, doing everything from the sig handler, unsafe, but this is only for debugging mode*/ handle_sigs(); }else{ /* process the important signals */ switch(signo){ case SIGPIPE: LM_INFO("signal %d received\n", signo); break; case SIGINT: case SIGTERM: LM_INFO("signal %d received\n", signo); /* print memory stats for non-main too */ #ifdef PKG_MALLOC LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); #endif exit(0); break; case SIGUSR1: /* statistics -> show only pkg mem */ #ifdef PKG_MALLOC LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); #endif break; case SIGUSR2: #ifdef PKG_MALLOC set_pkg_stats( get_pkg_status_holder(process_no) ); #endif break; case SIGHUP: /* ignored*/ break; case SIGCHLD: pid = waitpid(-1, &status, WNOHANG); LM_DBG("SIGCHLD received from %ld (status=%d), ignoring\n", (long)pid,status); } } }
/** * Clean up on exit. This should be called before exiting. * \param show_status set to one to display the mem status */ void cleanup(int show_status) { LM_INFO("cleanup\n"); /*clean-up*/ if (mem_lock) shm_unlock(); /* hack: force-unlock the shared memory lock in case some process crashed and let it locked; this will allow an almost gracious shutdown */ handle_ql_shutdown(); destroy_modules(); #ifdef USE_TCP destroy_tcp(); #endif #ifdef USE_TLS destroy_tls(); #endif destroy_timer(); destroy_stats_collector(); destroy_script_cb(); pv_free_extra_list(); destroy_argv_list(); destroy_black_lists(); #ifdef CHANGEABLE_DEBUG_LEVEL if (debug!=&debug_init) { reset_proc_debug_level(); debug_init = *debug; shm_free(debug); debug = &debug_init; } #endif #ifdef PKG_MALLOC if (show_status){ LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); } #endif #ifdef SHM_MEM if (pt) shm_free(pt); pt=0; if (show_status){ LM_GEN1(memdump, "Memory status (shm):\n"); shm_status(); } /* zero all shmem alloc vars that we still use */ shm_mem_destroy(); #endif if (pid_file) unlink(pid_file); if (pgid_file) unlink(pgid_file); }
void siplua_log(int lev, const char *format, ...) { va_list ap; char *ret; int priority; if (!format) return; if (!(is_printable(lev) | lua_user_debug)) return; va_start(ap, format); vasprintf(&ret, format, ap); va_end(ap); LM_GEN1(lev, "siplua: %s", ret); if (lua_user_debug) { switch (lev) { case L_ALERT: priority = LOG_ALERT; break; case L_CRIT: priority = LOG_CRIT; break; case L_ERR: priority = LOG_ERR; break; case L_WARN: priority = LOG_WARNING; break; case L_NOTICE: priority = LOG_NOTICE; break; case L_INFO: priority = LOG_INFO; break; case L_DBG: priority = LOG_DEBUG; break; default: /* should not happen, no execution path permits it */ priority = LOG_ERR; } syslog(LOG_USER | priority, "siplua: %s", ret); } free(ret); }
int xlog_2(struct sip_msg* msg, char* lev, char* frm) { int log_len; long level; xl_level_p xlp; pv_value_t value; xlp = (xl_level_p)lev; if(xlp->type==1) { if(pv_get_spec_value(msg, &xlp->v.sp, &value)!=0 || value.flags&PV_VAL_NULL || !(value.flags&PV_VAL_INT)) { LM_ERR("invalid log level value [%d]\n", value.flags); return -1; } level = (long)value.ri; } else { level = xlp->v.level; } if(!is_printable((int)level)) return 1; log_len = xlog_buf_size; if(xl_print_log(msg, (pv_elem_t*)frm, &log_len)<0) return -1; /* log_buf[log_len] = '\0'; */ LM_GEN1((int)level, "%.*s", log_len, log_buf); return 1; }
void vqm_status(struct vqm_block* qm) { struct vqm_frag* f; unsigned int i,on_list; LM_GEN1(memdump, "vqm_status (%p):\n", qm); if (!qm) return; LM_GEN1(memdump, " heap size= %d, available: %d\n", qm->core_end-qm->init_core, qm->free_core ); LM_GEN1(memdump, "dumping unfreed fragments:\n"); for (f=(struct vqm_frag*)qm->init_core, i=0;(char*)f<(char*)qm->core; f=FRAG_NEXT(f) ,i++) if ( FRAG_ISUSED(f) ) dump_frag(f, i); LM_GEN1(memdump, "dumping unfreed big fragments:\n"); for (f=(struct vqm_frag*)qm->big_chunks,i=0;(char*)f<(char*)qm->core_end; f=FRAG_NEXT(f) ,i++) if ( FRAG_ISUSED(f) ) dump_frag( f, i ); #ifdef DBG_QM_MALLOC LM_GEN1(memdump,"dumping bucket statistics:\n"); for (i=0; i<=BIG_BUCKET(qm); i++) { for(on_list=0, f=qm->next_free[i]; f; f=f->u.nxt_free ) on_list++; LM_GEN1(memdump," %3d. bucket: in use: %ld, on free list: %d\n", i, qm->usage[i], on_list ); } #endif LM_GEN1(memdump, "-----------------------------\n"); }
static void _print_entity(int index, b2bl_entity_id_t* e, int log_level) { b2bl_entity_id_t* c = e; while (c) { LM_GEN1(log_level, ".type=[%d] index=[%d] [%p]->[%.*s] state=%d no=%d" " dlginfo=[%p] peer=[%p] prev:next=[%p][%p]\n", c->type, index, c, c->key.len, c->key.s, c->state, c->no, c->dlginfo, c->peer, c->prev, c->next); if (c->dlginfo) LM_GEN1(log_level, "..........dlginfo=[%p]->[%.*s][%.*s][%.*s]\n", c->dlginfo, c->dlginfo->callid.len, c->dlginfo->callid.s, c->dlginfo->fromtag.len, c->dlginfo->fromtag.s, c->dlginfo->totag.len, c->dlginfo->totag.s); c = c->next; } }
void hp_status(struct hp_block *qm) { struct hp_frag* f; unsigned int i,j; unsigned int h; int unused; unsigned long size; LM_GEN1(memdump, "hp_status (%p):\n", qm); if (!qm) return; LM_GEN1(memdump, " heap size= %ld\n", qm->size); #ifdef STATISTICS LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n", qm->used, qm->real_used, qm->size-qm->used); LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used); #endif LM_GEN1(memdump, "dumping free list:\n"); for(h=0,i=0,size=0; h<HP_HASH_SIZE; h++) { unused=0; for (f=qm->free_hash[h].first,j=0; f; size+=f->size,f=f->u.nxt_free,i++,j++) { } if (j) LM_GEN1(memdump,"hash = %3d fragments no.: %5d, unused: %5d\n\t\t" " bucket size: %9lu - %9lu (first %9lu)\n", h, j, unused, UN_HASH(h), ((h<=HP_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h), qm->free_hash[h].first->size ); if (j!=qm->free_hash[h].no) { LM_CRIT("different free frag. count: %d!=%ld" " for hash %3d\n", j, qm->free_hash[h].no, h); } } LM_GEN1(memdump, "TOTAL: %6d free fragments = %6lu free bytes\n", i, size); LM_GEN1(memdump, "TOTAL: %ld large bytes\n", qm->large_space ); LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)FRAG_OVERHEAD ); LM_GEN1(memdump, "-----------------------------\n"); }
static inline void refresh_node( struct ip_node *node) { for( ; node ; node=node->next ) { node->hits[PREV_POS] = node->hits[CURR_POS]; node->hits[CURR_POS] = 0; node->leaf_hits[PREV_POS] = node->leaf_hits[CURR_POS]; node->leaf_hits[CURR_POS] = 0; if ( node->flags&NODE_ISRED_FLAG && !is_node_hot_leaf(node) ) { node->flags &= ~(NODE_ISRED_FLAG); LM_GEN1( pike_log_level,"PIKE - UNBLOCKing node %p\n",node); } if (node->kids) refresh_node( node->kids ); } }
int xdbg(struct sip_msg* msg, char* frm, char* str2) { int log_len; if(!is_printable(L_DBG)) return 1; log_len = xlog_buf_size; if(xl_print_log(msg, (pv_elem_t*)frm, &log_len)<0) return -1; /* log_buf[log_len] = '\0'; */ LM_GEN1(L_DBG, "%.*s", log_len, log_buf); return 1; }
static int sng_logger(int level, char *fmt, ...) { va_list args; static char buffer[256]; va_start(args, fmt); vsnprintf(buffer, 256, fmt, args); switch (level) { case SNGTC_LOGLEVEL_DEBUG: LM_GEN1(L_DBG, fmt, args); LM_DBG("%s\n", buffer); break; case SNGTC_LOGLEVEL_WARN: LM_GEN1(L_WARN, fmt, args); LM_WARN("%s\n", buffer); break; case SNGTC_LOGLEVEL_INFO: LM_GEN1(L_INFO, fmt, args); LM_INFO("%s\n", buffer); break; case SNGTC_LOGLEVEL_STATS: LM_GEN1(L_INFO, fmt, args); LM_INFO("%s\n", buffer); break; case SNGTC_LOGLEVEL_ERROR: LM_GEN1(L_ERR, fmt, args); LM_ERR("%s\n", buffer); break; case SNGTC_LOGLEVEL_CRIT: LM_GEN1(L_CRIT, fmt, args); LM_CRIT("%s\n", buffer); break; default: LM_GEN1(L_WARN, fmt, args); } va_end(args); return 0; }
void fm_status(struct fm_block* qm) { struct fm_frag* f; unsigned int i,j; unsigned int h; int unused; unsigned long size; #ifdef DBG_MALLOC mem_dbg_htable_t allocd; struct mem_dbg_entry *it; #endif LM_GEN1(memdump, "fm_status (%p):\n", qm); if (!qm) return; LM_GEN1(memdump, " heap size= %ld\n", qm->size); #if defined(DBG_MALLOC) || defined(STATISTICS) LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n", qm->used, qm->real_used, qm->size-qm->used); LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used); #endif #if defined(DBG_MALLOC) dbg_ht_init(allocd); for (f=qm->first_frag; (char*)f<(char*)qm->last_frag; f=FRAG_NEXT(f)) if (!f->is_free) if (dbg_ht_update(allocd, f->file, f->func, f->line, f->size) < 0) { LM_ERR("Unable to update alloc'ed. memory summary\n"); dbg_ht_free(allocd); return; } LM_GEN1(memdump, " dumping summary of all alloc'ed. fragments:\n"); for(i=0; i < DBG_HASH_SIZE; i++) { it = allocd[i]; while (it) { LM_GEN1(memdump, " %10lu : %lu x [%s: %s, line %lu]\n", it->size, it->no_fragments, it->file, it->func, it->line); it = it->next; } } dbg_ht_free(allocd); #endif LM_GEN1(memdump, "dumping free list:\n"); for(h=0,i=0,size=0; h<F_HASH_SIZE; h++) { unused=0; for (f=qm->free_hash[h].first,j=0; f; size+=f->size,f=f->u.nxt_free,i++,j++) { } if (j) LM_GEN1(memdump,"hash = %3d fragments no.: %5d, unused: %5d\n\t\t" " bucket size: %9lu - %9lu (first %9lu)\n", h, j, unused, UN_HASH(h), ((h<=F_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h), qm->free_hash[h].first->size ); if (j!=qm->free_hash[h].no) { LM_CRIT("different free frag. count: %d!=%ld" " for hash %3d\n", j, qm->free_hash[h].no, h); } } LM_GEN1(memdump, "TOTAL: %6d free fragments = %6lu free bytes\n", i, size); LM_GEN1(memdump, "TOTAL: %ld large bytes\n", qm->large_space ); LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)FRAG_OVERHEAD ); LM_GEN1(memdump, "-----------------------------\n"); }
void print_action(struct action* t) { switch(t->type){ case FORWARD_T: LM_GEN1(L_DBG, "forward("); break; case SEND_T: LM_GEN1(L_DBG, "send("); break; case ASSERT_T: LM_GEN1(L_DBG, "assert("); break; case DROP_T: LM_GEN1(L_DBG, "drop("); break; case LOG_T: LM_GEN1(L_DBG, "log("); break; case ERROR_T: LM_GEN1(L_DBG, "error("); break; case ROUTE_T: LM_GEN1(L_DBG, "route("); break; case EXEC_T: LM_GEN1(L_DBG, "exec("); break; case REVERT_URI_T: LM_GEN1(L_DBG, "revert_uri("); break; case STRIP_T: LM_GEN1(L_DBG, "strip("); break; case APPEND_BRANCH_T: LM_GEN1(L_DBG, "append_branch("); break; case PREFIX_T: LM_GEN1(L_DBG, "prefix("); break; case LEN_GT_T: LM_GEN1(L_DBG, "len_gt("); break; case SET_DEBUG_T: LM_GEN1(L_DBG, "setdebug("); break; case SETFLAG_T: LM_GEN1(L_DBG, "setflag("); break; case RESETFLAG_T: LM_GEN1(L_DBG, "resetflag("); break; case ISFLAGSET_T: LM_GEN1(L_DBG, "isflagset("); break; case SETBFLAG_T: LM_GEN1(L_DBG, "setbflag("); break; case RESETBFLAG_T: LM_GEN1(L_DBG, "resetbflag("); break; case ISBFLAGSET_T: LM_GEN1(L_DBG, "isbflagset("); break; case SETSFLAG_T: LM_GEN1(L_DBG, "setsflag("); break; case RESETSFLAG_T: LM_GEN1(L_DBG, "resetsflag("); break; case ISSFLAGSET_T: LM_GEN1(L_DBG, "issflagset("); break; case SET_HOST_T: LM_GEN1(L_DBG, "sethost("); break; case SET_HOSTPORT_T: LM_GEN1(L_DBG, "sethostport("); break; case SET_USER_T: LM_GEN1(L_DBG, "setuser("); break; case SET_USERPASS_T: LM_GEN1(L_DBG, "setuserpass("); break; case SET_PORT_T: LM_GEN1(L_DBG, "setport("); break; case SET_URI_T: LM_GEN1(L_DBG, "seturi("); break; case IF_T: LM_GEN1(L_DBG, "if ("); break; case WHILE_T: LM_GEN1(L_DBG, "while ("); break; case MODULE_T: LM_GEN1(L_DBG, " external_module_call("); break; case FORCE_RPORT_T: LM_GEN1(L_DBG, "force_rport("); break; case SET_ADV_ADDR_T: LM_GEN1(L_DBG, "set_advertised_address("); break; case SET_ADV_PORT_T: LM_GEN1(L_DBG, "set_advertised_port("); break; case FORCE_TCP_ALIAS_T: LM_GEN1(L_DBG, "force_tcp_alias("); break; case FORCE_SEND_SOCKET_T: LM_GEN1(L_DBG, "force_send_socket"); break; case RETURN_T: LM_GEN1(L_DBG, "return("); break; case EXIT_T: LM_GEN1(L_DBG, "exit("); break; case SWITCH_T: LM_GEN1(L_DBG, "switch("); break; case CASE_T: LM_GEN1(L_DBG, "case("); break; case DEFAULT_T: LM_GEN1(L_DBG, "default("); break; case SBREAK_T: LM_GEN1(L_DBG, "sbreak("); break; case EQ_T: LM_GEN1(L_DBG, "assign("); break; default: LM_GEN1(L_DBG, "UNKNOWN("); } switch(t->elem[0].type){ case STRING_ST: LM_GEN1(L_DBG, "\"%s\"", ZSW(t->elem[0].u.string)); break; case NUMBER_ST: LM_GEN1(L_DBG, "%lu",t->elem[0].u.number); break; case SCRIPTVAR_ST: LM_GEN1(L_DBG, "scriptvar[%d]",t->elem[0].u.item->type); break; case IP_ST: print_ip("", (struct ip_addr*)t->elem[0].u.data, ""); break; case EXPR_ST: print_expr((struct expr*)t->elem[0].u.data); break; case ACTIONS_ST: print_actions((struct action*)t->elem[0].u.data); break; case CMD_ST: LM_GEN1(L_DBG, "f<%s>",((cmd_export_t*)t->elem[0].u.data)->name); break; case SOCKID_ST: LM_GEN1(L_DBG, "%d:%s:%d", ((struct socket_id*)t->elem[0].u.data)->proto, ZSW(((struct socket_id*)t->elem[0].u.data)->name), ((struct socket_id*)t->elem[0].u.data)->port ); break; default: LM_GEN1(L_DBG, "type<%d>", t->elem[0].type); } if (t->type==IF_T) LM_GEN1(L_DBG, ") {"); switch(t->elem[1].type){ case NOSUBTYPE: break; case STRING_ST: LM_GEN1(L_DBG, ", \"%s\"", ZSW(t->elem[1].u.string)); break; case NUMBER_ST: LM_GEN1(L_DBG, ", %lu",t->elem[1].u.number); break; case EXPR_ST: print_expr((struct expr*)t->elem[1].u.data); break; case ACTIONS_ST: print_actions((struct action*)t->elem[1].u.data); break; case SOCKID_ST: LM_GEN1(L_DBG, "%d:%s:%d", ((struct socket_id*)t->elem[1].u.data)->proto, ZSW(((struct socket_id*)t->elem[1].u.data)->name), ((struct socket_id*)t->elem[1].u.data)->port ); break; default: LM_GEN1(L_DBG, ", type<%d>", t->elem[1].type); } if (t->type==IF_T && t->elem[2].type!=NOSUBTYPE) LM_GEN1(L_DBG, " } else { "); switch(t->elem[2].type){ case NOSUBTYPE: break; case STRING_ST: LM_GEN1(L_DBG, ", \"%s\"", ZSW(t->elem[2].u.string)); break; case NUMBER_ST: LM_GEN1(L_DBG, ", %lu",t->elem[2].u.number); break; case EXPR_ST: print_expr((struct expr*)t->elem[2].u.data); break; case ACTIONS_ST: print_actions((struct action*)t->elem[2].u.data); break; case SOCKID_ST: LM_GEN1(L_DBG, "%d:%s:%d", ((struct socket_id*)t->elem[2].u.data)->proto, ZSW(((struct socket_id*)t->elem[2].u.data)->name), ((struct socket_id*)t->elem[2].u.data)->port ); break; default: LM_GEN1(L_DBG, ", type<%d>", t->elem[2].type); } if (t->type==IF_T) LM_GEN1(L_DBG, "}; "); else LM_GEN1(L_DBG, "); "); }
static int _bm_log_timer(unsigned int id) { /* BM_CLOCK_REALTIME */ bm_timeval_t now; unsigned long long tdiff; benchmark_timer_t *timer; if (!timer_active(id)) return 1; if(bm_get_time(&now)<0) { LM_ERR("error getting current time\n"); return -1; } timer = bm_mycfg->tindex[id]; tdiff = bm_diff_time(timer->start, &now); _bm_last_time_diff = (int)tdiff; /* What to do * - update min, max, sum * - if granularity hit: Log, reset min/max */ lock_get(timer->lock); timer->sum += tdiff; timer->last_sum += tdiff; timer->calls++; timer->global_calls++; if (tdiff < timer->last_min) timer->last_min = tdiff; if (tdiff > timer->last_max) timer->last_max = tdiff; if (tdiff < timer->global_min) timer->global_min = tdiff; if (tdiff > timer->global_max) timer->global_max = tdiff; if (bm_mycfg->granularity > 0 && timer->calls >= bm_mycfg->granularity) { LM_GEN1(bm_mycfg->loglevel, "benchmark (timer %s [%d]): %llu [" " msgs/total/min/max/avg - LR:" " %i/%lld/%lld/%lld/%f | GB: %lld/%lld/%lld/%lld/%f]\n", timer->name, id, tdiff, timer->calls, timer->last_sum, timer->last_min, timer->last_max, ((double)timer->last_sum)/bm_mycfg->granularity, timer->global_calls, timer->sum, timer->global_min, timer->global_max, ((double)timer->sum)/timer->global_calls); soft_reset_timer(timer); } lock_release(timer->lock); return 1; }
int pike_check_req(struct sip_msg *msg) { struct ip_node *node; struct ip_node *father; unsigned char flags; struct ip_addr* ip; #ifdef _test /* get the ip address from second via */ if (parse_headers(msg, HDR_VIA1_F, 0)!=0 ) return -1; if (msg->via1==0 ) return -1; /* convert from string to ip_addr */ ip = str2ip( &msg->via1->host ); if (ip==0) return -1; #else ip = &(msg->rcv.src_ip); #endif /* first lock the proper tree branch and mark the IP with one more hit*/ lock_tree_branch( ip->u.addr[0] ); node = mark_node( ip->u.addr, ip->len, &father, &flags); if (node==0) { unlock_tree_branch( ip->u.addr[0] ); /* even if this is an error case, we return true in script to avoid * considering the IP as marked (bogdan) */ return 1; } LM_DBG("src IP [%s],node=%p; hits=[%d,%d],[%d,%d] node_flags=%d" " func_flags=%d\n", ip_addr2a( ip ), node, node->hits[PREV_POS],node->hits[CURR_POS], node->leaf_hits[PREV_POS],node->leaf_hits[CURR_POS], node->flags, flags); /* update the timer */ lock_get(timer_lock); if ( flags&NEW_NODE ) { /* put this node into the timer list and remove its father only if this has one kid and is not a LEAF_NODE*/ node->expires = get_ticks() + timeout; append_to_timer( timer, &(node->timer_ll) ); node->flags |= NODE_INTIMER_FLAG; if (father) { LM_DBG("father %p: flags=%d kids->next=%p\n", father,father->flags,father->kids->next); if (!(father->flags&NODE_IPLEAF_FLAG) && !father->kids->next){ /* debug */ assert( has_timer_set(&(father->timer_ll)) && (father->flags&(NODE_EXPIRED_FLAG|NODE_INTIMER_FLAG)) ); /* if the node is maked as expired by timer, let the timer * to finish and remove the node */ if ( !(father->flags&NODE_EXPIRED_FLAG) ) { remove_from_timer( timer, &(father->timer_ll) ); father->flags &= ~NODE_INTIMER_FLAG; } else { father->flags &= ~NODE_EXPIRED_FLAG; } } } } else { /* update the timer -> in timer can be only nodes * as IP-leaf(complete address) or tree-leaf */ if (node->flags&NODE_IPLEAF_FLAG || node->kids==0) { /* tree leafs which are not potential red nodes are not update in * order to make them to expire */ /* debug */ assert( has_timer_set(&(node->timer_ll)) && (node->flags&(NODE_EXPIRED_FLAG|NODE_INTIMER_FLAG)) ); /* if node exprired, ignore the current hit and let is * expire in timer process */ if ( !(flags&NO_UPDATE) && !(node->flags&NODE_EXPIRED_FLAG) ) { node->expires = get_ticks() + timeout; update_in_timer( timer, &(node->timer_ll) ); } } else { /* debug */ assert( !has_timer_set(&(node->timer_ll)) && !(node->flags&(NODE_INTIMER_FLAG|NODE_EXPIRED_FLAG)) ); /* debug */ assert( !(node->flags&NODE_IPLEAF_FLAG) && node->kids ); } } /*print_timer_list( timer );*/ /* debug*/ lock_release(timer_lock); unlock_tree_branch( ip->u.addr[0] ); /*print_tree( 0 );*/ /* debug */ if (flags&RED_NODE) { if (flags&NEWRED_NODE) { LM_GEN1( pike_log_level, "PIKE - BLOCKing ip %s, node=%p\n",ip_addr2a(ip),node); pike_raise_event(ip_addr2a(ip)); return -2; } return -1; } return 1; }
void vqm_free(struct vqm_block* qm, void* p) #endif { struct vqm_frag *f, *next, *prev, *first_big; unsigned char b; #ifdef DBG_QM_MALLOC LM_GEN1(memlog,"params (%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); if (p>(void *)qm->core_end || p<(void*)qm->init_core){ LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); abort(); } #endif if (p==0) { LM_WARN("free(0) called\n"); return; } f=(struct vqm_frag*) ((char*)p-sizeof(struct vqm_frag)); b=f->u.inuse.bucket; #ifdef DBG_QM_MALLOC VQM_DEBUG_FRAG(qm, f); if ( ! FRAG_ISUSED(f) ) { LM_CRIT("freeing already freed pointer, first freed: %s: %s(%d) " "- aborting\n", f->file, f->func, f->line); abort(); } if ( b>MAX_BUCKET ) { LM_CRIT("fragment with too high bucket nr: " "%d, allocated: %s: %s(%d) - aborting\n", b, f->file, f->func, f->line); abort(); } LM_GEN1(memlog,"freeing %d bucket block alloc'ed from %s: %s(%d)\n", f->u.inuse.bucket, f->file, f->func, f->line); f->file=file; f->func=func; f->line=line; qm->usage[ f->u.inuse.bucket ]--; #endif if (IS_BIGBUCKET(qm,b)) { next=FRAG_NEXT(f); if ((char *)next +sizeof( struct vqm_frag) < qm->core_end) { VQM_DEBUG_FRAG(qm, next); if (! FRAG_ISUSED(next)) { /* coalesce with next fragment */ LM_DBG("coalesced with next\n"); vqm_detach_free(qm, next); f->size+=next->size; FRAG_END(f)->size=f->size; } } first_big = qm->next_free[b]; if (first_big && f>first_big) { prev=FRAG_PREV(f); VQM_DEBUG_FRAG(qm, prev); if (!FRAG_ISUSED(prev)) { /* coalesce with prev fragment */ LM_DBG("coalesced with prev\n"); vqm_detach_free(qm, prev ); prev->size+=f->size; f=prev; FRAG_END(f)->size=f->size; } } if ((char *)f==qm->big_chunks) { /* release unused core */ LM_DBG("big chunk released\n"); qm->free_core+=f->size; qm->big_chunks+=f->size; return; } first_big = qm->next_free[b]; /* fix reverse link (used only for BIG_BUCKET */ if (first_big) FRAG_END(first_big)->prv_free=f; FRAG_END(f)->prv_free=0; } else first_big = qm->next_free[b]; f->u.nxt_free = first_big; /* also clobbers magic */ qm->next_free[b] = f; }
void print_expr(struct expr* exp) { if (exp==0){ LM_CRIT("null expression!\n"); return; } if (exp->type==ELEM_T){ switch(exp->left.type){ case METHOD_O: LM_GEN1(L_DBG, "method"); break; case URI_O: LM_GEN1(L_DBG, "uri"); break; case FROM_URI_O: LM_GEN1(L_DBG, "from_uri"); break; case TO_URI_O: LM_GEN1(L_DBG, "to_uri"); break; case SRCIP_O: LM_GEN1(L_DBG, "srcip"); break; case SRCPORT_O: LM_GEN1(L_DBG, "srcport"); break; case DSTIP_O: LM_GEN1(L_DBG, "dstip"); break; case DSTPORT_O: LM_GEN1(L_DBG, "dstport"); break; case SCRIPTVAR_O: LM_GEN1(L_DBG, "scriptvar[%d]", (exp->left.v.spec)?exp->left.v.spec->type:0); break; case NUMBER_O: case NUMBERV_O: LM_GEN1(L_DBG, "%d",exp->left.v.n); break; case STRINGV_O: LM_GEN1(L_DBG, "\"%s\"", ZSW((char*)exp->left.v.data)); break; case ACTION_O: break; case EXPR_O: print_expr((struct expr*)exp->left.v.data); break; default: LM_GEN1(L_DBG, "UNKNOWN[%d]", exp->left.type); } switch(exp->op){ case EQUAL_OP: LM_GEN1(L_DBG, "=="); break; case MATCHD_OP: case MATCH_OP: LM_GEN1(L_DBG, "=~"); break; case NOTMATCHD_OP: case NOTMATCH_OP: LM_GEN1(L_DBG, "!~"); break; case GT_OP: LM_GEN1(L_DBG, ">"); break; case GTE_OP: LM_GEN1(L_DBG, ">="); break; case LT_OP: LM_GEN1(L_DBG, "<"); break; case LTE_OP: LM_GEN1(L_DBG, "<="); break; case DIFF_OP: LM_GEN1(L_DBG, "!="); break; case PLUS_OP: LM_GEN1(L_DBG, "+"); break; case MINUS_OP: LM_GEN1(L_DBG, "-"); break; case DIV_OP: LM_GEN1(L_DBG, "/"); break; case MULT_OP: LM_GEN1(L_DBG, "*"); break; case MODULO_OP: LM_GEN1(L_DBG, " mod "); break; case BAND_OP: LM_GEN1(L_DBG, "&"); break; case BOR_OP: LM_GEN1(L_DBG, "|"); break; case BXOR_OP: LM_GEN1(L_DBG, "^"); break; case BLSHIFT_OP: LM_GEN1(L_DBG, "<<"); break; case BRSHIFT_OP: LM_GEN1(L_DBG, ">>"); break; case BNOT_OP: LM_GEN1(L_DBG, "~"); break; case VALUE_OP: case NO_OP: break; default: LM_GEN1(L_DBG, "<UNKNOWN[%d]>", exp->op); } switch(exp->right.type){ case NOSUBTYPE: /* LM_GEN1(L_DBG, "N/A"); */ break; case STRING_ST: LM_GEN1(L_DBG, "\"%s\"", ZSW((char*)exp->right.v.data)); break; case NET_ST: print_net((struct net*)exp->right.v.data); break; case IP_ST: print_ip("", (struct ip_addr*)exp->right.v.data, ""); break; case ACTIONS_ST: print_actions((struct action*)exp->right.v.data); break; case NUMBER_ST: LM_GEN1(L_DBG, "%d",exp->right.v.n); break; case MYSELF_ST: LM_GEN1(L_DBG, "_myself_"); break; case SCRIPTVAR_ST: LM_GEN1(L_DBG, "scriptvar[%d]", exp->right.v.spec->type); break; case NULLV_ST: LM_GEN1(L_DBG, "null"); break; case EXPR_ST: print_expr((struct expr*)exp->right.v.data); break; default: LM_GEN1(L_DBG, "type<%d>", exp->right.type); } }else if (exp->type==EXP_T){ switch(exp->op){ case AND_OP: LM_GEN1(L_DBG, "AND( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case OR_OP: LM_GEN1(L_DBG, "OR( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case NOT_OP: LM_GEN1(L_DBG, "NOT( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, " )"); break; case EVAL_OP: LM_GEN1(L_DBG, "EVAL( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, " )"); break; case PLUS_OP: LM_GEN1(L_DBG, "PLUS( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case MINUS_OP: LM_GEN1(L_DBG, "MINUS( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case DIV_OP: LM_GEN1(L_DBG, "DIV( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case MULT_OP: LM_GEN1(L_DBG, "MULT( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case MODULO_OP: LM_GEN1(L_DBG, "MODULO( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case BAND_OP: LM_GEN1(L_DBG, "BAND( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case BOR_OP: LM_GEN1(L_DBG, "BOR( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case BXOR_OP: LM_GEN1(L_DBG, "BXOR( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case BLSHIFT_OP: LM_GEN1(L_DBG, "BLSHIFT( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case BRSHIFT_OP: LM_GEN1(L_DBG, "BRSHIFT( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, ", "); print_expr(exp->right.v.expr); LM_GEN1(L_DBG, " )"); break; case BNOT_OP: LM_GEN1(L_DBG, "BNOT( "); print_expr(exp->left.v.expr); LM_GEN1(L_DBG, " )"); break; default: LM_GEN1(L_DBG, "UNKNOWN_EXP[%d] ", exp->op); } }else{ LM_ERR("unknown type\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; }
int _bm_log_timer(unsigned int id) { /* BM_CLOCK_REALTIME */ bm_timeval_t now; unsigned long long tdiff; if (!timer_active(id)) return 1; if(bm_get_time(&now)<0) { LM_ERR("error getting current time\n"); return -1; } tdiff = bm_diff_time(bm_mycfg->tindex[id]->start, &now); _bm_last_time_diff = (int)tdiff; /* What to do * - update min, max, sum * - if granularity hit: Log, reset min/max */ bm_mycfg->tindex[id]->sum += tdiff; bm_mycfg->tindex[id]->last_sum += tdiff; bm_mycfg->tindex[id]->calls++; if (tdiff < bm_mycfg->tindex[id]->last_min) bm_mycfg->tindex[id]->last_min = tdiff; if (tdiff > bm_mycfg->tindex[id]->last_max) bm_mycfg->tindex[id]->last_max = tdiff; if (tdiff < bm_mycfg->tindex[id]->global_min) bm_mycfg->tindex[id]->global_min = tdiff; if (tdiff > bm_mycfg->tindex[id]->global_max) bm_mycfg->tindex[id]->global_max = tdiff; if ((bm_mycfg->tindex[id]->calls % bm_mycfg->granularity) == 0) { LM_GEN1(bm_mycfg->loglevel, "benchmark (timer %s [%d]): %llu [" " msgs/total/min/max/avg - LR:" " %i/%llu/%llu/%llu/%f | GB: %llu/%llu/%llu/%llu/%f]\n", bm_mycfg->tindex[id]->name, id, tdiff, bm_mycfg->granularity, bm_mycfg->tindex[id]->last_sum, bm_mycfg->tindex[id]->last_min, bm_mycfg->tindex[id]->last_max, ((double)bm_mycfg->tindex[id]->last_sum)/bm_mycfg->granularity, bm_mycfg->tindex[id]->calls, bm_mycfg->tindex[id]->sum, bm_mycfg->tindex[id]->global_min, bm_mycfg->tindex[id]->global_max, ((double)bm_mycfg->tindex[id]->sum)/bm_mycfg->tindex[id]->calls); bm_mycfg->tindex[id]->last_sum = 0; bm_mycfg->tindex[id]->last_max = 0; bm_mycfg->tindex[id]->last_min = 0xffffffff; } return 1; }
void hp_status(struct hp_block *hpb) { struct hp_frag *f; int i, j, si, t = 0; int h; LM_GEN1(memdump, "hp_status (%p, ROUNDTO=%ld):\n", hpb, ROUNDTO); if (!hpb) return; LM_GEN1(memdump, "%20s : %ld\n", "HP_HASH_SIZE", HP_HASH_SIZE); LM_GEN1(memdump, "%20s : %ld\n", "HP_EXTRA_HASH_SIZE", HP_HASH_SIZE); LM_GEN1(memdump, "%20s : %ld\n", "HP_TOTAL_SIZE", HP_HASH_SIZE); LM_GEN1(memdump, "%20s : %ld\n", "total_size", hpb->size); #ifdef STATISTICS LM_GEN1(memdump, "%20s : %lu\n%20s : %lu\n%20s : %lu\n", "used", hpb->used, "used+overhead", hpb->real_used, "free", hpb->size - hpb->used); LM_GEN1(memdump, "%20s : %lu\n\n", "max_used (+overhead)", hpb->max_real_used); #endif LM_GEN1(memdump, "Dumping free fragments:\n"); for (h = 0; h < HP_HASH_SIZE; h++) { if (hpb->free_hash[h].is_optimized) { LM_GEN1(memdump, "[ %4d ][ %5d B ][ frags: ", h, h * (int)ROUNDTO); for (si = HP_HASH_SIZE + h * shm_secondary_hash_size, j = 0; j < shm_secondary_hash_size; j++, si++, t++) { SHM_LOCK(si); for (i=0, f=hpb->free_hash[si].first; f; f=f->u.nxt_free, i++, t++) ; SHM_UNLOCK(si); LM_GEN1(memdump, "%s%5d ", j == 0 ? "" : "| ", i); } LM_GEN1(memdump, "]\n"); } else { SHM_LOCK(h); for (i=0, f=hpb->free_hash[h].first; f; f=f->u.nxt_free, i++, t++) ; SHM_UNLOCK(h); if (i == 0) continue; if (h > HP_LINEAR_HASH_SIZE) { LM_GEN1(memdump, "[ %4d ][ %8d B -> %7d B ][ frags: %5d ]\n", h, (int)UN_HASH(h), (int)UN_HASH(h+1) - (int)ROUNDTO, i); } else LM_GEN1(memdump, "[ %4d ][ %5d B ][ frags: %5d ]\n", h, h * (int)ROUNDTO, i); } } LM_GEN1(memdump, "TOTAL: %6d free fragments\n", t); LM_GEN1(memdump, "TOTAL: %ld large bytes\n", hpb->large_space ); LM_GEN1(memdump, "TOTAL: %u overhead\n", (unsigned int)FRAG_OVERHEAD ); LM_GEN1(memdump, "-----------------------------\n"); }
void* fm_malloc(struct fm_block* qm, unsigned long size) #endif { struct fm_frag* frag,*n; unsigned int hash; #ifdef DBG_MALLOC LM_GEN1(memlog, "%s_malloc(%lu), called from %s: %s(%d)\n", qm->name, size, file, func, line); #endif /*size must be a multiple of 8*/ size=ROUNDUP(size); /*search for a suitable free frag*/ for(hash=GET_HASH(size); hash<F_HASH_SIZE; hash++) { frag=qm->free_hash[hash].first; for( ; frag; frag = frag->u.nxt_free ) if ( frag->size >= size ) goto found; /* try in a bigger bucket */ } /* not found, bad! */ #if defined(DBG_MALLOC) || defined(STATISTICS) LM_ERR(oom_errorf, qm->name, qm->size - qm->real_used, qm->name[0] == 'p' ? "M" : "m"); LM_INFO("attempting defragmentation... (need %lu bytes)\n", size); #else LM_ERR(oom_nostats_errorf, qm->name, qm->name[0] == 'p' ? "M" : "m"); LM_INFO("attempting defragmentation... (need %lu bytes)\n", size); #endif for( frag = qm->first_frag; (char*)frag < (char*)qm->last_frag; ) { n = FRAG_NEXT(frag); if ( ((char*)n < (char*)qm->last_frag) && n->prev && frag->prev ) { /* detach frag*/ fm_remove_free(qm, frag); do { fm_remove_free(qm, n); frag->size += n->size + FRAG_OVERHEAD; #if defined(DBG_MALLOC) || defined(STATISTICS) //qm->real_used -= FRAG_OVERHEAD; qm->used += FRAG_OVERHEAD; #endif if( frag->size >size ) { #ifdef DBG_MALLOC /* mark it as "busy" */ frag->is_free = 0; #endif goto solved; } n = FRAG_NEXT(frag); } while ( ((char*)n < (char*)qm->last_frag) && n->prev); fm_insert_free(qm,frag); } frag = n; } LM_INFO("unable to alloc a big enough fragment!\n"); pkg_threshold_check(); return 0; found: /* we found it!*/ fm_remove_free(qm,frag); #ifdef DBG_MALLOC /* mark it as "busy" */ frag->is_free = 0; #endif /*see if we'll use full frag, or we'll split it in 2*/ #ifdef DBG_MALLOC fm_split_frag(qm, frag, size, file, func, line); frag->file=file; frag->func=func; frag->line=line; frag->check=ST_CHECK_PATTERN; LM_GEN1(memlog, "%s_malloc(%lu), returns address %p\n", qm->name, size, (char*)frag+sizeof(struct fm_frag)); #else fm_split_frag(qm, frag, size); #endif solved: #if defined(DBG_MALLOC) || defined(STATISTICS) if (qm->max_real_used<qm->real_used) qm->max_real_used=qm->real_used; qm->fragments += 1; #endif pkg_threshold_check(); return (char*)frag+sizeof(struct fm_frag); }
/** * Signal handler for the server. */ void handle_sigs(void) { pid_t chld; int chld_status; int i; int do_exit; const unsigned int shutdown_time = 60; /* one minute close timeout */ switch(sig_flag){ case 0: break; /* do nothing*/ case SIGPIPE: /* SIGPIPE might be rarely received on use of exec module; simply ignore it */ LM_WARN("SIGPIPE received and ignored\n"); break; case SIGINT: case SIGTERM: /* we end the program in all these cases */ if (sig_flag==SIGINT) LM_DBG("INT received, program terminates\n"); else LM_DBG("SIGTERM received, program terminates\n"); /* first of all, kill the children also */ kill_all_children(SIGTERM); if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) { LM_ERR("could not install SIGALARM handler\n"); /* continue, the process will die anyway if no * alarm is installed which is exactly what we want */ } alarm(shutdown_time); while(wait(0) > 0); /* Wait for all the children to terminate */ signal(SIGALRM, sig_alarm_abort); cleanup(1); /* cleanup & show status*/ alarm(0); signal(SIGALRM, SIG_IGN); dprint("Thank you for flying " NAME "\n"); exit(0); break; case SIGUSR1: #ifdef PKG_MALLOC LM_GEN1(memdump, "Memory status (pkg):\n"); pkg_status(); #endif #ifdef SHM_MEM LM_GEN1(memdump, "Memory status (shm):\n"); shm_status(); #endif break; case SIGUSR2: #ifdef PKG_MALLOC set_pkg_stats( get_pkg_status_holder(process_no) ); #endif break; case SIGCHLD: do_exit = 0; while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) { /* is it a process we know about? */ for( i=0 ; i<counted_processes ; i++ ) if (pt[i].pid==chld) break; if (i==counted_processes) { LM_DBG("unkown child process %d ended. Ignoring\n",chld); continue; } do_exit = 1; /* process the signal */ if (WIFEXITED(chld_status)) LM_INFO("child process %d exited normally," " status=%d\n", chld, WEXITSTATUS(chld_status)); else if (WIFSIGNALED(chld_status)) { LM_INFO("child process %d exited by a signal" " %d\n", chld, WTERMSIG(chld_status)); #ifdef WCOREDUMP LM_INFO("core was %sgenerated\n", WCOREDUMP(chld_status) ? "" : "not " ); #endif }else if (WIFSTOPPED(chld_status)) LM_INFO("child process %d stopped by a" " signal %d\n", chld, WSTOPSIG(chld_status)); } if (!do_exit) break; LM_INFO("terminating due to SIGCHLD\n"); /* exit */ kill_all_children(SIGTERM); if (signal(SIGALRM, sig_alarm_kill) == SIG_ERR ) { LM_ERR("could not install SIGALARM handler\n"); /* continue, the process will die anyway if no * alarm is installed which is exactly what we want */ } alarm(shutdown_time); while(wait(0) > 0); /* wait for all the children to terminate*/ signal(SIGALRM, sig_alarm_abort); cleanup(1); /* cleanup & show status*/ alarm(0); signal(SIGALRM, SIG_IGN); LM_DBG("terminating due to SIGCHLD\n"); exit(0); break; case SIGHUP: /* ignoring it*/ LM_DBG("SIGHUP received, ignoring it\n"); break; default: LM_CRIT("unhandled signal %d\n", sig_flag); } sig_flag=0; }
void* vqm_malloc(struct vqm_block* qm, unsigned int size) #endif { struct vqm_frag *new_chunk, *f; unsigned char bucket; #ifdef DBG_QM_MALLOC unsigned int demanded_size; LM_GEN1( memlog, "params (%p, %d) called from %s: %s(%d)\n", qm, size, file, func, line); demanded_size = size; #endif new_chunk=0; /* what's the bucket? what's the total size incl. overhead? */ bucket = size2bucket( qm, &size ); if (IS_BIGBUCKET(qm, bucket)) { /* the kilo-bucket uses first-fit */ #ifdef DBG_QM_MALLOC LM_GEN1( memlog, "processing a big fragment\n"); #endif for (f=qm->next_free[bucket] ; f; f=f->u.nxt_free ) if (f->size>=size) { /* first-fit */ new_chunk=f; VQM_DEBUG_FRAG(qm, f); vqm_detach_free(qm,f); break; } } else if ( (new_chunk=qm->next_free[ bucket ]) ) { /*fixed size bucket*/ VQM_DEBUG_FRAG(qm, new_chunk); /*detach it from the head of bucket's free list*/ qm->next_free[ bucket ] = new_chunk->u.nxt_free; } if (!new_chunk) { /* no chunk can be reused; slice one from the core */ new_chunk=MORE_CORE( qm, bucket, size ); if (!new_chunk) { #ifdef DBG_QM_MALLOC LM_GEN1(memlog, "params (%p, %d) called from %s: %s(%d)\n", qm, size, file, func, line); #else LM_DBG("params (%p, %d) called from %s: %s(%d)\n", qm, size); #endif return 0; } } new_chunk->u.inuse.magic = FR_USED; new_chunk->u.inuse.bucket=bucket; #ifdef DBG_QM_MALLOC new_chunk->file=file; new_chunk->func=func; new_chunk->line=line; new_chunk->demanded_size=demanded_size; qm->usage[ bucket ]++; LM_GEN1( memlog,"params ( %p, %d ) returns address %p in bucket %d, " "real-size %d\n", qm, demanded_size, (char*)new_chunk+sizeof(struct vqm_frag), bucket, size ); new_chunk->end_check=(char*)new_chunk+ sizeof(struct vqm_frag)+demanded_size; memcpy( new_chunk->end_check, END_CHECK_PATTERN, END_CHECK_PATTERN_LEN ); new_chunk->check=ST_CHECK_PATTERN; #endif return (char*)new_chunk+sizeof(struct vqm_frag); }
int split_frag(struct qm_block* qm, struct qm_frag* f, unsigned long new_size) #endif { unsigned long rest; struct qm_frag* n; struct qm_frag_end* end; rest=f->size-new_size; #ifdef MEM_FRAG_AVOIDANCE if ((rest> (FRAG_OVERHEAD+QM_MALLOC_OPTIMIZE))|| (rest>=(FRAG_OVERHEAD+new_size))){/* the residue fragm. is big enough*/ #else if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){ #endif f->size=new_size; /*split the fragment*/ end=FRAG_END(f); end->size=new_size; n=(struct qm_frag*)((char*)end+sizeof(struct qm_frag_end)); n->size=rest-FRAG_OVERHEAD; FRAG_END(n)->size=n->size; FRAG_CLEAR_USED(n); /* never used */ qm->real_used+=FRAG_OVERHEAD; #ifdef DBG_QM_MALLOC end->check1=END_CHECK_PATTERN1; end->check2=END_CHECK_PATTERN2; /* frag created by malloc, mark it*/ n->file=file; n->func=func; n->line=line; n->check=ST_CHECK_PATTERN; #endif /* reinsert n in free list*/ qm_insert_free(qm, n); return 0; }else{ /* we cannot split this fragment any more */ return -1; } } #ifdef DBG_QM_MALLOC void* qm_malloc(struct qm_block* qm, unsigned long size, const char* file, const char* func, unsigned int line) #else void* qm_malloc(struct qm_block* qm, unsigned long size) #endif { struct qm_frag* f; int hash; #ifdef DBG_QM_MALLOC unsigned int list_cntr; list_cntr = 0; LM_GEN1( memlog, "params (%p, %lu), called from %s: %s(%d)\n", qm, size, file, func, line); #endif /*size must be a multiple of 8*/ size=ROUNDUP(size); if (size>(qm->size-qm->real_used)) return 0; /*search for a suitable free frag*/ #ifdef DBG_QM_MALLOC if ((f=qm_find_free(qm, size, &hash, &list_cntr))!=0){ #else if ((f=qm_find_free(qm, size, &hash))!=0){ #endif /* we found it!*/ /*detach it from the free list*/ #ifdef DBG_QM_MALLOC qm_debug_frag(qm, f); #endif qm_detach_free(qm, f); /*mark it as "busy"*/ f->u.is_free=0; qm->free_hash[hash].no--; /* we ignore split return */ #ifdef DBG_QM_MALLOC split_frag(qm, f, size, file, "fragm. from qm_malloc", line); #else split_frag(qm, f, size); #endif qm->real_used+=f->size; qm->used+=f->size; if (qm->max_real_used<qm->real_used) qm->max_real_used=qm->real_used; #ifdef DBG_QM_MALLOC f->file=file; f->func=func; f->line=line; f->check=ST_CHECK_PATTERN; /* FRAG_END(f)->check1=END_CHECK_PATTERN1; FRAG_END(f)->check2=END_CHECK_PATTERN2;*/ LM_GEN1( memlog, "params (%p, %lu), returns address %p frag. %p " "(size=%lu) on %d -th hit\n", qm, size, (char*)f+sizeof(struct qm_frag), f, f->size, list_cntr ); #endif return (char*)f+sizeof(struct qm_frag); } return 0; } #ifdef DBG_QM_MALLOC void qm_free(struct qm_block* qm, void* p, const char* file, const char* func, unsigned int line) #else void qm_free(struct qm_block* qm, void* p) #endif { struct qm_frag* f; unsigned long size; #ifdef QM_JOIN_FREE struct qm_frag* next; struct qm_frag* prev; #endif #ifdef DBG_QM_MALLOC LM_GEN1( memlog, "params(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); if (p>(void*)qm->last_frag_end || p<(void*)qm->first_frag){ LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); abort(); } #endif if (p==0) { LM_WARN("free(0) called\n"); return; } #ifdef QM_JOIN_FREE prev=next=0; #endif f=(struct qm_frag*) ((char*)p-sizeof(struct qm_frag)); #ifdef DBG_QM_MALLOC qm_debug_frag(qm, f); if (f->u.is_free){ LM_CRIT("freeing already freed pointer," " first free: %s: %s(%ld) - aborting\n", f->file, f->func, f->line); abort(); } LM_GEN1( memlog, "freeing frag. %p alloc'ed from %s: %s(%ld)\n", f, f->file, f->func, f->line); #endif size=f->size; qm->used-=size; qm->real_used-=size; #ifdef QM_JOIN_FREE /* join packets if possible*/ next=FRAG_NEXT(f); if (((char*)next < (char*)qm->last_frag_end) &&( next->u.is_free)){ /* join */ #ifdef DBG_QM_MALLOC qm_debug_frag(qm, next); #endif qm_detach_free(qm, next); size+=next->size+FRAG_OVERHEAD; qm->real_used-=FRAG_OVERHEAD; qm->free_hash[GET_HASH(next->size)].no--; /* FIXME slow */ } if (f > qm->first_frag){ prev=FRAG_PREV(f); /* (struct qm_frag*)((char*)f - (struct qm_frag_end*)((char*)f- sizeof(struct qm_frag_end))->size);*/ #ifdef DBG_QM_MALLOC qm_debug_frag(qm, prev); #endif if (prev->u.is_free){ /*join*/ qm_detach_free(qm, prev); size+=prev->size+FRAG_OVERHEAD; qm->real_used-=FRAG_OVERHEAD; qm->free_hash[GET_HASH(prev->size)].no--; /* FIXME slow */ f=prev; } } f->size=size; FRAG_END(f)->size=f->size; #endif /* QM_JOIN_FREE*/ #ifdef DBG_QM_MALLOC f->file=file; f->func=func; f->line=line; #endif qm_insert_free(qm, f); } #ifdef DBG_QM_MALLOC void* qm_realloc(struct qm_block* qm, void* p, unsigned long size, const char* file, const char* func, unsigned int line) #else void* qm_realloc(struct qm_block* qm, void* p, unsigned long size) #endif { struct qm_frag* f; unsigned long diff; unsigned long orig_size; struct qm_frag* n; void* ptr; #ifdef DBG_QM_MALLOC LM_GEN1( memlog, "params (%p, %p, %lu), called from %s: %s(%d)\n", qm, p, size, file, func, line); if ((p)&&(p>(void*)qm->last_frag_end || p<(void*)qm->first_frag)){ LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); abort(); } #endif if (size==0) { if (p) #ifdef DBG_QM_MALLOC qm_free(qm, p, file, func, line); #else qm_free(qm, p); #endif return 0; } if (p==0) #ifdef DBG_QM_MALLOC return qm_malloc(qm, size, file, func, line); #else return qm_malloc(qm, size); #endif f=(struct qm_frag*) ((char*)p-sizeof(struct qm_frag)); #ifdef DBG_QM_MALLOC qm_debug_frag(qm, f); LM_GEN1( memlog, "realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", f, f->file, f->func, f->line); if (f->u.is_free){ LM_CRIT("trying to realloc an already freed " "pointer %p , fragment %p -- aborting\n", p, f); abort(); } #endif /* find first acceptable size */ size=ROUNDUP(size); if (f->size > size){ orig_size=f->size; /* shrink */ #ifdef DBG_QM_MALLOC LM_GEN1(memlog,"shrinking from %lu to %lu\n", f->size, size); if(split_frag(qm, f, size, file, "fragm. from qm_realloc", line)!=0){ LM_GEN1(memlog,"shrinked successful\n"); #else if(split_frag(qm, f, size)!=0){ #endif /* update used sizes: freed the spitted frag */ qm->real_used-=(orig_size-f->size-FRAG_OVERHEAD); qm->used-=(orig_size-f->size); } }else if (f->size < size){ /* grow */ #ifdef DBG_QM_MALLOC LM_GEN1( memlog, "growing from %lu to %lu\n", f->size, size); #endif orig_size=f->size; diff=size-f->size; n=FRAG_NEXT(f); if (((char*)n < (char*)qm->last_frag_end) && (n->u.is_free)&&((n->size+FRAG_OVERHEAD)>=diff)){ /* join */ qm_detach_free(qm, n); qm->free_hash[GET_HASH(n->size)].no--; /*FIXME: slow*/ f->size+=n->size+FRAG_OVERHEAD; qm->real_used-=FRAG_OVERHEAD; FRAG_END(f)->size=f->size; /* end checks should be ok */ /* split it if necessary */ if (f->size > size ){ #ifdef DBG_QM_MALLOC split_frag(qm, f, size, file, "fragm. from qm_realloc", line); #else split_frag(qm, f, size); #endif } qm->real_used+=(f->size-orig_size); qm->used+=(f->size-orig_size); }else{ /* could not join => realloc */ #ifdef DBG_QM_MALLOC ptr=qm_malloc(qm, size, file, func, line); #else ptr=qm_malloc(qm, size); #endif if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); #ifdef DBG_QM_MALLOC qm_free(qm, p, file, func, line); #else qm_free(qm, p); #endif } p=ptr; } }else{ /* do nothing */ #ifdef DBG_QM_MALLOC LM_GEN1(memlog,"doing nothing, same size: %lu - %lu\n", f->size, size); #endif } #ifdef DBG_QM_MALLOC LM_GEN1(memlog,"returning %p\n", p); #endif return p; } void qm_status(struct qm_block* qm) { struct qm_frag* f; int i,j; int h; int unused; LM_GEN1(memdump, "qm_status (%p):\n", qm); if (!qm) return; LM_GEN1(memdump, " heap size= %lu\n", qm->size); LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n", qm->used, qm->real_used, qm->size-qm->real_used); LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used); LM_GEN1(memdump, "dumping all alloc'ed. fragments:\n"); for (f=qm->first_frag, i=0;(char*)f<(char*)qm->last_frag_end;f=FRAG_NEXT(f) ,i++){ if (! f->u.is_free){ LM_GEN1(memdump," %3d. %c address=%p frag=%p size=%lu used=%d\n", i, (f->u.is_free)?'a':'N', (char*)f+sizeof(struct qm_frag), f, f->size, FRAG_WAS_USED(f)); #ifdef DBG_QM_MALLOC LM_GEN1(memdump, " %s from %s: %s(%ld)\n", (f->u.is_free)?"freed":"alloc'd", f->file, f->func, f->line); LM_GEN1(memdump, " start check=%lx, end check= %lx, %lx\n", f->check, FRAG_END(f)->check1, FRAG_END(f)->check2); #endif } } LM_GEN1(memdump, "dumping free list stats :\n"); for(h=0,i=0;h<QM_HASH_SIZE;h++){ unused=0; for (f=qm->free_hash[h].head.u.nxt_free,j=0; f!=&(qm->free_hash[h].head); f=f->u.nxt_free, i++, j++){ if (!FRAG_WAS_USED(f)){ unused++; #ifdef DBG_QM_MALLOC LM_GEN1(memdump, "unused fragm.: hash = %3d, fragment %p," " address %p size %lu, created from %s: %s(%lu)\n", h, f, (char*)f+sizeof(struct qm_frag), f->size, f->file, f->func, f->line); #endif } } if (j) LM_GEN1(memdump, "hash= %3d. fragments no.: %5d, unused: %5d\n" "\t\t bucket size: %9lu - %9ld (first %9lu)\n", h, j, unused, UN_HASH(h), ((h<=QM_MALLOC_OPTIMIZE/ROUNDTO)?1:2)*UN_HASH(h), qm->free_hash[h].head.u.nxt_free->size ); if (j!=qm->free_hash[h].no){ LM_CRIT("different free frag. count: %d!=%lu" " for hash %3d\n", j, qm->free_hash[h].no, h); } } LM_GEN1(memdump, "-----------------------------\n"); } /* fills a malloc info structure with info about the block * if a parameter is not supported, it will be filled with 0 */ void qm_info(struct qm_block* qm, struct mem_info* info) { int r; long total_frags; total_frags=0; memset(info,0, sizeof(*info)); info->total_size=qm->size; info->min_frag=MIN_FRAG_SIZE; info->free=qm->size-qm->real_used; info->used=qm->used; info->real_used=qm->real_used; info->max_used=qm->max_real_used; for(r=0;r<QM_HASH_SIZE; r++){ total_frags+=qm->free_hash[r].no; } info->total_frags=total_frags; }
void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) #endif { struct fm_frag *f; unsigned long diff; unsigned long orig_size; struct fm_frag *n; void *ptr; #ifdef DBG_MALLOC LM_GEN1(memlog, "%s_realloc(%p, %lu->%lu), called from %s: %s(%d)\n", qm->name, p, p ? ((struct fm_frag*)((char *)p - sizeof(struct fm_frag)))->size:0, size, file, func, line); if ((p)&&(p>(void*)qm->last_frag || p<(void*)qm->first_frag)) { LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); abort(); } #endif if (size==0) { if (p) #ifdef DBG_MALLOC fm_free(qm, p, file, func, line); #else fm_free(qm, p); #endif pkg_threshold_check(); return 0; } if (p==0) #ifdef DBG_MALLOC return fm_malloc(qm, size, file, func, line); #else return fm_malloc(qm, size); #endif f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag)); #ifdef DBG_MALLOC LM_GEN1(memlog, "realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", f, f->file, f->func, f->line); #endif size=ROUNDUP(size); orig_size=f->size; if (f->size > size) { /* shrink */ #ifdef DBG_MALLOC LM_GEN1(memlog, "shrinking from %lu to %lu\n", f->size, size); fm_split_frag(qm, f, size, file, "frag. from fm_realloc", line); #else fm_split_frag(qm, f, size); #endif } else if (f->size<size) { /* grow */ #ifdef DBG_MALLOC LM_GEN1(memlog, "growing from %lu to %lu\n", f->size, size); #endif diff=size-f->size; n=FRAG_NEXT(f); if (((char*)n < (char*)qm->last_frag) && n->prev && ((n->size+FRAG_OVERHEAD)>=diff)) { fm_remove_free(qm,n); /* join */ f->size += n->size + FRAG_OVERHEAD; #if defined(DBG_MALLOC) || defined(STATISTICS) //qm->real_used -= FRAG_OVERHEAD; qm->used += FRAG_OVERHEAD; #endif /* split it if necessary */ if (f->size > size) { #ifdef DBG_MALLOC fm_split_frag(qm, f, size, file, "fragm. from fm_realloc", line); #else fm_split_frag(qm, f, size); #endif } } else { /* could not join => realloc */ #ifdef DBG_MALLOC ptr=fm_malloc(qm, size, file, func, line); #else ptr = fm_malloc(qm, size); #endif if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); #ifdef DBG_MALLOC fm_free(qm, p, file, func, line); #else fm_free(qm, p); #endif } p = ptr; } } else { /* do nothing */ #ifdef DBG_MALLOC LM_GEN1(memlog, "doing nothing, same size: %lu - %lu\n", f->size, size); #endif } #ifdef DBG_MALLOC LM_GEN1(memlog, "returning %p\n", p); #endif #if defined(DBG_MALLOC) || defined(STATISTICS) if (qm->max_real_used<qm->real_used) qm->max_real_used=qm->real_used; #endif pkg_threshold_check(); return p; }