int w_rl_check_3(struct sip_msg *_m, char *_n, char *_l, char *_a) { str name; int limit = 0, ret = 1, should_update = 0; str algorithm; unsigned int hash_idx; rl_pipe_t **pipe; rl_algo_t algo = -1; /* retrieve and check parameters */ if (!_n || !_l) { LM_ERR("invalid parameters\n"); goto end; } if (fixup_get_svalue(_m, (gparam_p)_n, &name) < 0) { LM_ERR("cannot retrieve identifier\n"); goto end; } if (fixup_get_ivalue(_m, (gparam_p)_l, &limit) < 0) { LM_ERR("cannot retrieve limit\n"); goto end; } algorithm.s = 0; if (!_a || fixup_get_svalue(_m, (gparam_p)_a, &algorithm) < 0 || (algo = get_rl_algo(algorithm)) < 0) { algo = PIPE_ALGO_NOP; } /* get limit for FEEDBACK algorithm */ if (algo == PIPE_ALGO_FEEDBACK) { lock_get(rl_lock); if (*rl_feedback_limit) { if (*rl_feedback_limit != limit) { LM_WARN("FEEDBACK limit should be the same for all pipes, but" " new limit %d differs - setting to %d\n", limit, *rl_feedback_limit); limit = *rl_feedback_limit; } } else { if (limit <= 0 || limit >= 100) { LM_ERR("invalid limit for FEEDBACK algorithm " "(must be between 0 and 100)\n"); lock_release(rl_lock); goto end; } *rl_feedback_limit = limit; pid_setpoint_limit(limit); } lock_release(rl_lock); } hash_idx = RL_GET_INDEX(name); RL_GET_LOCK(hash_idx); /* try to get the value */ pipe = RL_GET_PIPE(hash_idx, name); if (!pipe) { LM_ERR("cannot get the index\n"); goto release; } if (!*pipe) { /* allocate new pipe */ *pipe = shm_malloc(sizeof(rl_pipe_t) + rl_dests_nr * sizeof(rl_repl_counter_t)); if (!*pipe) { LM_ERR("no more shm memory\n"); goto release; } memset(*pipe, 0, sizeof(rl_pipe_t) + rl_dests_nr * sizeof(rl_repl_counter_t)); (*pipe)->dsts = (rl_repl_counter_t *)((*pipe) + 1); LM_DBG("Pipe %.*s doens't exist, but was created %p\n", name.len, name.s, *pipe); if (algo == PIPE_ALGO_NETWORK) should_update = 1; (*pipe)->algo = (algo == PIPE_ALGO_NOP) ? rl_default_algo : algo; } else { LM_DBG("Pipe %.*s found: %p - last used %lu\n", name.len, name.s, *pipe, (*pipe)->last_used); if (algo != PIPE_ALGO_NOP && (*pipe)->algo != algo) { LM_WARN("algorithm %d different from the initial one %d for pipe " "%.*s", algo, (*pipe)->algo, name.len, name.s); } } /* set/update the limit */ (*pipe)->limit = limit; /* set the last used time */ (*pipe)->last_used = time(0); if (RL_USE_CDB(*pipe)) { /* release the counter for a while */ if (rl_change_counter(&name, *pipe, 1) < 0) { LM_ERR("cannot increase counter\n"); goto end; } } else { (*pipe)->counter++; } ret = rl_pipe_check(*pipe); LM_DBG("Pipe %.*s counter:%d load:%d limit:%d should %sbe blocked (%p)\n", name.len, name.s, (*pipe)->counter, (*pipe)->load, (*pipe)->limit, ret == 1? "NOT " : "", *pipe); release: RL_RELEASE_LOCK(hash_idx); if (should_update) { lock_get(rl_lock); (*rl_network_count)++; lock_release(rl_lock); } end: return ret; }
int w_rl_check(struct sip_msg *_m, str *name, int *limit, str *algorithm) { int ret = 1, should_update = 0; unsigned int hash_idx; rl_pipe_t **pipe; rl_algo_t algo = -1; if (!algorithm || (algo = get_rl_algo(*algorithm)) == PIPE_ALGO_NOP) { algo = PIPE_ALGO_NOP; } /* get limit for FEEDBACK algorithm */ if (algo == PIPE_ALGO_FEEDBACK) { lock_get(rl_lock); if (*rl_feedback_limit) { if (*rl_feedback_limit != *limit) { LM_WARN("FEEDBACK limit should be the same for all pipes, but" " new limit %d differs - setting to %d\n", *limit, *rl_feedback_limit); *limit = *rl_feedback_limit; } } else { if (*limit <= 0 || *limit >= 100) { LM_ERR("invalid limit for FEEDBACK algorithm " "(must be between 0 and 100)\n"); lock_release(rl_lock); goto end; } *rl_feedback_limit = *limit; pid_setpoint_limit(*limit); } lock_release(rl_lock); } hash_idx = RL_GET_INDEX(*name); RL_GET_LOCK(hash_idx); /* try to get the value */ pipe = RL_GET_PIPE(hash_idx, *name); if (!pipe) { LM_ERR("cannot get the index\n"); goto release; } if (!*pipe) { /* allocate new pipe */ if (!(*pipe = rl_create_pipe(*limit, algo))) goto release; LM_DBG("Pipe %.*s doesn't exist, but was created %p\n", name->len, name->s, *pipe); if ((*pipe)->algo == PIPE_ALGO_NETWORK) should_update = 1; } else { LM_DBG("Pipe %.*s found: %p - last used %lu\n", name->len, name->s, *pipe, (*pipe)->last_used); if (algo != PIPE_ALGO_NOP && (*pipe)->algo != algo) { LM_WARN("algorithm %d different from the initial one %d for pipe " "%.*s", algo, (*pipe)->algo, name->len, name->s); } /* update the limit */ (*pipe)->limit = *limit; } /* set the last used time */ (*pipe)->last_used = time(0); if (RL_USE_CDB(*pipe)) { /* release the counter for a while */ if (rl_change_counter(name, *pipe, 1) < 0) { LM_ERR("cannot increase counter\n"); goto release; } } else { (*pipe)->counter++; } ret = rl_pipe_check(*pipe); LM_DBG("Pipe %.*s counter:%d load:%d limit:%d should %sbe blocked (%p)\n", name->len, name->s, (*pipe)->counter, (*pipe)->load, (*pipe)->limit, ret == 1 ? "NOT " : "", *pipe); release: RL_RELEASE_LOCK(hash_idx); if (should_update) { lock_get(rl_lock); (*rl_network_count)++; lock_release(rl_lock); } end: return ret; }