|
|
@ -37,19 +37,24 @@ static bool |
|
|
|
redis_connect(cfg_t *cfg) { |
|
|
|
redis_connect(cfg_t *cfg) { |
|
|
|
assert(cfg != NULL); |
|
|
|
assert(cfg != NULL); |
|
|
|
|
|
|
|
|
|
|
|
redisReply *reply; |
|
|
|
if (cfg->conn && !cfg->conn->err) |
|
|
|
struct timeval timeout = { cfg->timeout, 0 }; |
|
|
|
return true; /* connected */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
redisContext *conn = NULL; |
|
|
|
|
|
|
|
redisReply *reply = NULL; |
|
|
|
do { |
|
|
|
do { |
|
|
|
cfg->conn = redisConnectWithTimeout(cfg->host, cfg->port, timeout); |
|
|
|
struct timeval timeout = { cfg->timeout, 0 }; |
|
|
|
if (cfg->conn->err) { |
|
|
|
conn = redisConnectWithTimeout(cfg->host, cfg->port, timeout); |
|
|
|
|
|
|
|
if (!conn) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
if (conn->err) { |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "Connection error: %s", cfg->conn->errstr); |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "Connection error: %s", cfg->conn->errstr); |
|
|
|
return false; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (cfg->password[0]) { |
|
|
|
if (cfg->password[0]) { |
|
|
|
reply = redisCommand(cfg->conn, "AUTH %s", cfg->password); |
|
|
|
reply = redisCommand(cfg->conn, "AUTH %s", cfg->password); |
|
|
|
if (reply->type == REDIS_REPLY_ERROR) { |
|
|
|
if (reply->type == REDIS_REPLY_ERROR) { |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str); |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str); |
|
|
|
freeReplyObject(reply); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
freeReplyObject(reply); |
|
|
|
freeReplyObject(reply); |
|
|
@ -58,16 +63,21 @@ redis_connect(cfg_t *cfg) { |
|
|
|
reply = redisCommand(cfg->conn, "SELECT %d", cfg->database); |
|
|
|
reply = redisCommand(cfg->conn, "SELECT %d", cfg->database); |
|
|
|
if (reply->type == REDIS_REPLY_ERROR) { |
|
|
|
if (reply->type == REDIS_REPLY_ERROR) { |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str); |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str); |
|
|
|
freeReplyObject(reply); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
freeReplyObject(reply); |
|
|
|
freeReplyObject(reply); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (cfg->conn) |
|
|
|
|
|
|
|
redisFree(cfg->conn); |
|
|
|
|
|
|
|
cfg->conn = conn; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} while (0); |
|
|
|
} while (0); |
|
|
|
|
|
|
|
|
|
|
|
redisFree(cfg->conn); |
|
|
|
if (conn) |
|
|
|
cfg->conn = NULL; |
|
|
|
redisFree(conn); |
|
|
|
|
|
|
|
if (reply) |
|
|
|
|
|
|
|
freeReplyObject(reply); |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -80,13 +90,6 @@ redis_disconnect(cfg_t *cfg) { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool |
|
|
|
|
|
|
|
redis_reconnect(cfg_t *cfg) { |
|
|
|
|
|
|
|
redis_disconnect(cfg); |
|
|
|
|
|
|
|
return redis_connect(cfg); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* handlers */ |
|
|
|
|
|
|
|
cfg_t * |
|
|
|
cfg_t * |
|
|
|
create(const char *id) { |
|
|
|
create(const char *id) { |
|
|
|
cfg_t *cfg = NULL; |
|
|
|
cfg_t *cfg = NULL; |
|
|
@ -159,8 +162,7 @@ start(cfg_t *cfg) { |
|
|
|
if (cfg->shared && usage_inc(cfg->name) > 1) |
|
|
|
if (cfg->shared && usage_inc(cfg->name) > 1) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
redis_connect(cfg); |
|
|
|
return redis_connect(cfg); |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
bool |
|
|
@ -170,14 +172,16 @@ stop(cfg_t *cfg) { |
|
|
|
if (cfg->shared && usage_dec(cfg->name) > 0) |
|
|
|
if (cfg->shared && usage_dec(cfg->name) > 0) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
redis_disconnect(cfg); |
|
|
|
return redis_disconnect(cfg); |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
bool |
|
|
|
ban(cfg_t *cfg, const char *ip) { |
|
|
|
ban(cfg_t *cfg, const char *ip) { |
|
|
|
assert(cfg != NULL); |
|
|
|
assert(cfg != NULL); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!redis_connect(cfg)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
redisReply *reply; |
|
|
|
redisReply *reply; |
|
|
|
do { |
|
|
|
do { |
|
|
|
reply = redisCommand(cfg->conn, "HINCRBY %s %s %d", cfg->hash, ip, 1); |
|
|
|
reply = redisCommand(cfg->conn, "HINCRBY %s %s %d", cfg->hash, ip, 1); |
|
|
@ -204,6 +208,7 @@ ban(cfg_t *cfg, const char *ip) { |
|
|
|
bool |
|
|
|
bool |
|
|
|
unban(cfg_t *cfg, const char *ip) { |
|
|
|
unban(cfg_t *cfg, const char *ip) { |
|
|
|
assert(cfg != NULL); |
|
|
|
assert(cfg != NULL); |
|
|
|
|
|
|
|
|
|
|
|
(void)(ip); /* suppress warning for unused variable 'ip' */ |
|
|
|
(void)(ip); /* suppress warning for unused variable 'ip' */ |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@ -212,43 +217,36 @@ bool |
|
|
|
check(cfg_t *cfg, const char *ip) { |
|
|
|
check(cfg_t *cfg, const char *ip) { |
|
|
|
assert(cfg != NULL); |
|
|
|
assert(cfg != NULL); |
|
|
|
|
|
|
|
|
|
|
|
bool exists; |
|
|
|
(void)(ip); /* suppress warning for unused variable 'ip' */ |
|
|
|
redisReply *reply; |
|
|
|
|
|
|
|
do { |
|
|
|
|
|
|
|
reply = redisCommand(cfg->conn, "HEXISTS %s %s", cfg->hash, ip); |
|
|
|
|
|
|
|
if (reply && reply->type == REDIS_REPLY_ERROR) { |
|
|
|
|
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "PUBLISH: %s", reply->str); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (reply && reply->integer == REDIS_REPLY_INTEGER) |
|
|
|
|
|
|
|
exists = reply->integer ? true : false; |
|
|
|
|
|
|
|
freeReplyObject(reply); |
|
|
|
|
|
|
|
return exists; |
|
|
|
|
|
|
|
} while (0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (reply) |
|
|
|
|
|
|
|
freeReplyObject(reply); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
bool |
|
|
|
ping(cfg_t *cfg) { |
|
|
|
ping(cfg_t *cfg) { |
|
|
|
assert(cfg != NULL); |
|
|
|
assert(cfg != NULL); |
|
|
|
redisReply *reply = redisCommand(cfg->conn, "PING"); |
|
|
|
|
|
|
|
|
|
|
|
if (!cfg->conn || cfg->conn->err) |
|
|
|
|
|
|
|
redis_connect(cfg); |
|
|
|
|
|
|
|
if (!cfg->conn) |
|
|
|
|
|
|
|
return false; /* reconnect failure */ |
|
|
|
|
|
|
|
|
|
|
|
if (cfg->conn->err) { |
|
|
|
if (cfg->conn->err) { |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "connection error: %s", cfg->conn->errstr); |
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "connection error: %s", cfg->conn->errstr); |
|
|
|
redis_reconnect(cfg); |
|
|
|
return false; |
|
|
|
return cfg->conn->err ? false : true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if (reply && reply->type == REDIS_REPLY_ERROR) { |
|
|
|
|
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "%s", reply->str); |
|
|
|
redisReply *reply = redisCommand(cfg->conn, "PING"); |
|
|
|
|
|
|
|
if (reply) { |
|
|
|
|
|
|
|
bool result = true; |
|
|
|
|
|
|
|
if (reply->type == REDIS_REPLY_ERROR) { |
|
|
|
|
|
|
|
snprintf(cfg->error, sizeof(cfg->error), "%s", reply->str); |
|
|
|
|
|
|
|
result = false; |
|
|
|
|
|
|
|
} |
|
|
|
freeReplyObject(reply); |
|
|
|
freeReplyObject(reply); |
|
|
|
return false; |
|
|
|
return result; |
|
|
|
} else { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|