Skip to content

Commit

Permalink
Fixes and test HELLO functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
attipaci committed Dec 8, 2024
1 parent 211809b commit ac6abfd
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 24 deletions.
2 changes: 1 addition & 1 deletion config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ CC ?= gcc
CPPFLAGS += -I$(INC)

# Base compiler options (if not defined externally...)
CFLAGS ?= -Os -Wall -std=c99
CFLAGS ?= -g -Os -Wall -std=c99

# Extra warnings (not supported on all compilers)
#CFLAGS += -Wextra
Expand Down
7 changes: 4 additions & 3 deletions include/redisx.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ enum redisx_protocol {
*/
typedef struct RESP {
enum resp_type type; ///< RESP type RESP_ARRAY, RESP_INT ...
int n; ///< Either the integer value of a RESP_INT response, or the
int n; ///< Either the integer value of a RESP_INT or a RESP3_BOOLEAN response, or the
///< dimension of the value field.
void *value; ///< Pointer to text (char *) content or to an array of components
///< (RESP**)...
///< (RESP**) or (RedisMapEntry *), or else a pointer to a `double`, depending
///< on `type`.
} RESP;

/**
Expand All @@ -186,7 +187,7 @@ typedef struct {
typedef struct RedisEntry {
char *key; ///< The Redis key or field name
char *value; ///< The string value stored for that field.
int length; ///< Bytes in value.
int length; ///< Bytes in value.
} RedisEntry;


Expand Down
25 changes: 19 additions & 6 deletions src/redisx-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,13 +601,24 @@ int redisxSendArrayRequestAsync(RedisClient *cl, char *args[], int lengths[], in
// Send the number of string elements in the command...
L = sprintf(buf, "*%d\r\n", n);


xvprintf("Redis-X> request[%d]", n);
for(i = 0; i < n; i++) {
if(args[i]) xvprintf(" %s", args[i]);
if(i == 4) {
xvprintf("...");
}
}
xvprintf("\n");

for(i = 0; i < n; i++) {
int l, L1;

if(!args[i]) l = 0; // Check for potential NULL parameters...
else if(!lengths) l = (int) strlen(args[i]);
else l = lengths[i] > 0 ? lengths[i] : (int) strlen(args[i]);


L += sprintf(buf + L, "$%d\r\n", l);

// length of next RESP the bulk string component including \r\n\0 termination.
Expand Down Expand Up @@ -876,7 +887,6 @@ RESP *redisxReadReplyAsync(RedisClient *cl) {
else break;
}


// Now get the body of the response...
if(!status) switch(resp->type) {

Expand Down Expand Up @@ -932,7 +942,7 @@ RESP *redisxReadReplyAsync(RedisClient *cl) {
}

// Consistency check. Discard response if incomplete (because of read errors...)
if(component) for(i = 0; i < resp->n; i++) if(component[i] == NULL || component[i]->type != RESP3_NULL) {
if(component) for(i = 0; i < resp->n; i++) if(component[i] == NULL || component[i]->type == RESP3_NULL) {
fprintf(stderr, "WARNING! Redis-X : incomplete array received (index %d of %d).\n", (i+1), resp->n);
if(!status) status = REDIS_INCOMPLETE_TRANSFER;
break;
Expand All @@ -945,18 +955,21 @@ RESP *redisxReadReplyAsync(RedisClient *cl) {

case RESP3_MAP:
case RESP3_ATTRIBUTE: {
RedisMapEntry *component;
RedisMapEntry *dict;
int i;

if(resp->n <= 0) break;

component = (RedisMapEntry *) calloc(resp->n, sizeof(RedisMapEntry));
x_check_alloc(component);
dict = (RedisMapEntry *) calloc(resp->n, sizeof(RedisMapEntry));
x_check_alloc(dict);

for(i=0; i<resp->n; i++) {
RedisMapEntry *e = &component[i];
RedisMapEntry *e = &dict[i];
e->key = redisxReadReplyAsync(cl);
e->value = redisxReadReplyAsync(cl);
}
resp->value = dict;

break;
}

Expand Down
26 changes: 17 additions & 9 deletions src/redisx-net.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,6 @@ int rConnectClient(Redis *redis, enum redisx_channel channel) {
if(p->hello) {
char proto[20];
char *args[6];
RESP *reply;
int k = 0;

args[k++] = "HELLO";
Expand All @@ -584,21 +583,30 @@ int rConnectClient(Redis *redis, enum redisx_channel channel) {

if(p->password) {
args[k++] = "AUTH";
args[k++] = p->username ? p->username : "default";
args[k++] = p->password;
}

args[k++] = "SETNAME";
args[k++] = id;

reply = redisxArrayRequest(redis, args, NULL, k, &status);
if(redisxCheckRESP(reply, RESP3_MAP, 0)) {
// OK, it looks like HELLO worked...
RedisMapEntry *e = redisxGetKeywordEntry(reply, "proto");
if(e && e->value->type == RESP_INT) p->protocol = e->value->n;
p->hello = FALSE;

status = redisxSendArrayRequestAsync(cl, args, NULL, k);
if(status == X_SUCCESS) {
RESP *reply = redisxReadReplyAsync(cl);
status = redisxCheckRESP(reply, RESP3_MAP, 0);
if(status == X_SUCCESS) {
RedisMapEntry *e = redisxGetKeywordEntry(reply, "proto");
if(e && e->value->type == RESP_INT) {
p->protocol = e->value->n;
xvprintf("Confirmed protocol %d\n", p->protocol);
}
p->hello = TRUE;
}
else xvprintf("! Redis-X: HELLO failed: %s\n", redisxErrorDescription(status));
redisxDestroyRESP(reply);
}
else p->hello = FALSE;

redisxDestroyRESP(reply);
}

if(!p->hello) {
Expand Down
2 changes: 0 additions & 2 deletions src/redisx-tab.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ int redisxSetValue(Redis *redis, const char *table, const char *key, const char
if(redis == NULL) return x_error(X_NULL, EINVAL, fn, "redis is NULL");

prop_error(fn, redisxLockConnected(redis->interactive));

status = redisxSetValueAsync(redis->interactive, table, key, value, confirm);

redisxUnlockClient(redis->interactive);

prop_error(fn, status);
Expand Down
2 changes: 0 additions & 2 deletions src/redisx.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,6 @@ RESP *redisxArrayRequest(Redis *redis, char *args[], int lengths[], int n, int *
}
else *status = X_SUCCESS;

xvprintf("Redis-X> request %s... [%d].\n", args[0], n);

cl = redis->interactive;
*status = redisxLockConnected(cl);
if(*status) return x_trace_null(fn, NULL);
Expand Down
5 changes: 4 additions & 1 deletion src/resp.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
void redisxDestroyRESP(RESP *resp) {
if(resp == NULL) return;

switch(resp->type) {
if(resp->value) switch(resp->type) {
case RESP_ARRAY:
case RESP3_SET:
case RESP3_PUSH: {
Expand Down Expand Up @@ -151,6 +151,9 @@ int redisxCheckRESP(const RESP *resp, enum resp_type expectedType, int expectedS
static const char *fn = "redisxCheckRESP";

if(resp == NULL) return x_error(X_NULL, EINVAL, fn, "RESP is NULL");
if(resp->type == RESP3_BOOLEAN) {
if(resp->n != (expectedSize ? 1 : 0)) return x_error(X_FAILURE, EBADMSG, fn, "unexpected boolean value: expected %d, got %d", (expectedSize ? 1 : 0), resp->n);
}
if(resp->type != RESP_INT && resp->type != RESP3_NULL) {
if(resp->n < 0) return x_error(X_FAILURE, EBADMSG, fn, "RESP error code: %d", resp->n);
if(resp->value == NULL) if(resp->n) return x_error(REDIS_NULL, ENOMSG, fn, "RESP with NULL value, n=%d", resp->n);
Expand Down
35 changes: 35 additions & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Use the parent directories for libraries and headers.
LIB = ../lib
INC = ../include
BUILD_MODE = debug

ifdef XCHANGE
XCHANGE := ../$(XCHANGE)
endif

# Load the common Makefile definitions...
include ../config.mk

.PHONY: all
all: tests run

.PHONY: tests
tests: $(BIN)/test-hello

.PHONY: run
run: tests
$(BIN)/test-hello

$(BIN)/test-%: $(OBJ)/test-%.o $(LIB)/libredisx.a
make $(BIN)
$(CC) -o $@ $^ $(LDFLAGS) -lredisx

.PHONY: clean-test
clean-test:
rm -rf bin

clean: clean-test

# Finally, the standard generic rules and targets...
include ../build.mk

53 changes: 53 additions & 0 deletions test/src/test-hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* @file
*
* @date Created on Dec 8, 2024
* @author Attila Kovacs
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "redisx.h"
#include "xchange.h"

int main() {

Redis *redis = redisxInit("localhost");
RedisEntry *e;
int n = -1;

xSetDebug(TRUE);
//redisxSetVerbose(TRUE);
//redisxDebugTraffic(TRUE);

redisxSetProtocol(redis, REDISX_RESP3);

if(redisxConnect(redis, FALSE) < 0) {
perror("ERROR! connect");
return 1;
}

if(redisxGetProtocol(redis) != REDISX_RESP3) {
fprintf(stderr, "ERROR! verify RESP3 protocol\n");
return 1;
}

if(redisxSetValue(redis, "_test_", "_value_", "1", TRUE) < 0) {
perror("ERROR! set value");
return 1;
}

e = redisxGetTable(redis, "_test_", &n);
if(n <= 0) return 1;

redisxDestroyEntries(e, n);
redisxDisconnect(redis);
redisxDestroy(redis);

fprintf(stderr, "OK\n");

return 0;

}

0 comments on commit ac6abfd

Please sign in to comment.