From a298d3c16bfde9966e816a61da8e6f531eaebe13 Mon Sep 17 00:00:00 2001 From: Nicolas Favre-Felix Date: Tue, 25 Jan 2011 18:44:57 +0100 Subject: [PATCH] Better client/cmd relationship. --- client.c | 3 +++ client.h | 2 ++ cmd.c | 11 ++++++----- cmd.h | 3 +-- formats/common.c | 24 +++++++++++++----------- formats/common.h | 6 ++++-- formats/custom-type.c | 14 +++++++------- formats/json.c | 28 ++++++++++++++-------------- formats/json.h | 2 +- formats/raw.c | 5 ++--- 10 files changed, 53 insertions(+), 45 deletions(-) diff --git a/client.c b/client.c index fe783d2..13ac3af 100644 --- a/client.c +++ b/client.c @@ -118,6 +118,9 @@ http_client_cleanup(struct http_client *c) { memset(&c->verb, 0, sizeof(c->verb)); + cmd_free(c->cmd); + c->cmd = NULL; + c->state = CLIENT_WAITING; } diff --git a/client.h b/client.h index d8e0cc3..29c66ea 100644 --- a/client.h +++ b/client.h @@ -7,6 +7,7 @@ #include "http.h" struct server; +struct cmd; typedef enum { CLIENT_WAITING, @@ -21,6 +22,7 @@ struct http_client { struct event ev; struct server *s; client_state state; + struct cmd *cmd; /* http parser */ http_parser_settings settings; diff --git a/cmd.c b/cmd.c index 1f6f960..77f585e 100644 --- a/cmd.c +++ b/cmd.c @@ -14,11 +14,10 @@ #include struct cmd * -cmd_new(struct http_client *client, int count) { +cmd_new(int count) { struct cmd *c = calloc(1, sizeof(struct cmd)); - c->client = client; c->count = count; c->argv = calloc(count, sizeof(char*)); @@ -31,6 +30,8 @@ cmd_new(struct http_client *client, int count) { void cmd_free(struct cmd *c) { + if(!c) return; + free(c->argv); free(c->argv_len); @@ -95,7 +96,7 @@ cmd_run(struct server *s, struct http_client *client, param_count++; } - cmd = cmd_new(client, param_count); + client->cmd = cmd = cmd_new(param_count); /* get output formatting function */ uri_len = cmd_select_format(client, cmd, uri, uri_len, &f_format); @@ -128,7 +129,7 @@ cmd_run(struct server *s, struct http_client *client, /* no args (e.g. INFO command) */ if(!slash) { - redisAsyncCommandArgv(s->ac, f_format, cmd, 1, cmd->argv, cmd->argv_len); + redisAsyncCommandArgv(s->ac, f_format, client, 1, cmd->argv, cmd->argv_len); return 0; } p = slash + 1; @@ -156,7 +157,7 @@ cmd_run(struct server *s, struct http_client *client, } /* push command to Redis. */ - redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len); + redisAsyncCommandArgv(s->ac, f_format, client, cmd->count, cmd->argv, cmd->argv_len); for(i = 1; i < cur_param; ++i) { free((char*)cmd->argv[i]); diff --git a/cmd.h b/cmd.h index 9733593..052216f 100644 --- a/cmd.h +++ b/cmd.h @@ -18,7 +18,6 @@ struct cmd { int count; const char **argv; size_t *argv_len; - struct http_client *client; int started_responding; @@ -33,7 +32,7 @@ struct subscription { }; struct cmd * -cmd_new(struct http_client *client, int count); +cmd_new(int count); void cmd_free(struct cmd *c); diff --git a/formats/common.c b/formats/common.c index 5f61916..e057e1f 100644 --- a/formats/common.c +++ b/formats/common.c @@ -30,10 +30,12 @@ char *etag_new(const char *p, size_t sz) { } void -format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content_type) { +format_send_reply(struct http_client *client, const char *p, size_t sz, const char *content_type) { int free_cmd = 1; + struct cmd *cmd = client->cmd; + if(cmd_is_subscribe(cmd)) { free_cmd = 0; @@ -41,32 +43,32 @@ format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content if(cmd->started_responding == 0) { const char *ct = cmd->mime?cmd->mime:content_type; cmd->started_responding = 1; - http_set_header(&cmd->client->output_headers.content_type, ct, strlen(ct)); - http_send_reply_start(cmd->client, 200, "OK"); + http_set_header(&client->output_headers.content_type, ct, strlen(ct)); + http_send_reply_start(client, 200, "OK"); } - http_send_reply_chunk(cmd->client, p, sz); + http_send_reply_chunk(client, p, sz); } else { /* compute ETag */ char *etag = etag_new(p, sz); - const char *if_none_match = cmd->client->input_headers.if_none_match.s; + const char *if_none_match = client->input_headers.if_none_match.s; /* check If-None-Match */ - if(if_none_match && strncmp(if_none_match, etag, cmd->client->input_headers.if_none_match.sz) == 0) { + if(if_none_match && strncmp(if_none_match, etag, client->input_headers.if_none_match.sz) == 0) { /* SAME! send 304. */ - http_send_reply(cmd->client, 304, "Not Modified", NULL, 0); + http_send_reply(client, 304, "Not Modified", NULL, 0); } else { const char *ct = cmd->mime?cmd->mime:content_type; - http_set_header(&cmd->client->output_headers.content_type, ct, strlen(ct)); - http_set_header(&cmd->client->output_headers.etag, etag, strlen(etag)); - http_send_reply(cmd->client, 200, "OK", p, sz); + http_set_header(&client->output_headers.content_type, ct, strlen(ct)); + http_set_header(&client->output_headers.etag, etag, strlen(etag)); + http_send_reply(client, 200, "OK", p, sz); } free(etag); } /* cleanup */ if(free_cmd) { - cmd_free(cmd); + cmd_free(client->cmd); } } diff --git a/formats/common.h b/formats/common.h index c47c4f2..199d7f3 100644 --- a/formats/common.h +++ b/formats/common.h @@ -3,9 +3,11 @@ #include -struct cmd; +struct http_client; void -format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content_type); +format_send_reply(struct http_client *client, + const char *p, size_t sz, + const char *content_type); #endif diff --git a/formats/custom-type.c b/formats/custom-type.c index 26eb13d..0c7e7f8 100644 --- a/formats/custom-type.c +++ b/formats/custom-type.c @@ -12,7 +12,7 @@ void custom_type_reply(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; - struct cmd *cmd = privdata; + struct http_client *client = privdata; (void)c; char int_buffer[50]; int int_len; @@ -21,26 +21,26 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) { return; } - if(cmd->mime) { /* use the given content-type, but only for strings */ + if(client->cmd->mime) { /* use the given content-type, but only for strings */ switch(reply->type) { case REDIS_REPLY_NIL: /* or nil values */ - format_send_reply(cmd, "", 0, cmd->mime); + format_send_reply(client, "", 0, client->cmd->mime); return; case REDIS_REPLY_STRING: - format_send_reply(cmd, reply->str, reply->len, cmd->mime); + format_send_reply(client, reply->str, reply->len, client->cmd->mime); return; case REDIS_REPLY_INTEGER: int_len = sprintf(int_buffer, "%lld", reply->integer); - format_send_reply(cmd, int_buffer, int_len, cmd->mime); + format_send_reply(client, int_buffer, int_len, client->cmd->mime); return; } } /* couldn't make sense of what the client wanted. */ - http_send_reply(cmd->client, 400, "Bad request", NULL, 0); - cmd_free(cmd); + http_send_reply(client, 400, "Bad request", NULL, 0); + cmd_free(client->cmd); } diff --git a/formats/json.c b/formats/json.c index 6ef2f4e..160a834 100644 --- a/formats/json.c +++ b/formats/json.c @@ -15,12 +15,12 @@ void json_reply(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; - struct cmd *cmd = privdata; + struct http_client *client = privdata; json_t *j; char *jstr; (void)c; - if(cmd == NULL) { + if(client->cmd == NULL) { /* broken connection */ return; } @@ -30,13 +30,15 @@ json_reply(redisAsyncContext *c, void *r, void *privdata) { } /* encode redis reply as JSON */ - j = json_wrap_redis_reply(cmd, r); + j = json_wrap_redis_reply(client->cmd, r); /* get JSON as string, possibly with JSONP wrapper */ - jstr = json_string_output(j, cmd); + jstr = json_string_output(j, + client->query_string.jsonp.s, + client->query_string.jsonp.sz); /* send reply */ - format_send_reply(cmd, jstr, strlen(jstr), "application/json"); + format_send_reply(client, jstr, strlen(jstr), "application/json"); /* cleanup */ json_decref(j); @@ -107,22 +109,20 @@ json_wrap_redis_reply(const struct cmd *cmd, const redisReply *r) { char * -json_string_output(json_t *j, struct cmd *cmd) { +json_string_output(json_t *j, const char *jsonp, size_t jsonp_len) { char *json_reply = json_dumps(j, JSON_COMPACT); /* check for JSONP */ - if(cmd->client->query_string.jsonp.s) { - + if(jsonp) { size_t json_len = strlen(json_reply); - size_t val_len = cmd->client->query_string.jsonp.sz; - size_t ret_len = val_len + 1 + json_len + 3; + size_t ret_len = jsonp_len + 1 + json_len + 3; char *ret = calloc(1 + ret_len, 1); - memcpy(ret, cmd->client->query_string.jsonp.s, val_len); - ret[val_len]='('; - memcpy(ret + val_len + 1, json_reply, json_len); - memcpy(ret + val_len + 1 + json_len, ");\n", 3); + memcpy(ret, jsonp, jsonp_len); + ret[jsonp_len]='('; + memcpy(ret + jsonp_len + 1, json_reply, json_len); + memcpy(ret + jsonp_len + 1 + json_len, ");\n", 3); free(json_reply); return ret; diff --git a/formats/json.h b/formats/json.h index a81d6cb..bc68e8c 100644 --- a/formats/json.h +++ b/formats/json.h @@ -11,6 +11,6 @@ void json_reply(redisAsyncContext *c, void *r, void *privdata); char * -json_string_output(json_t *j, struct cmd *cmd); +json_string_output(json_t *j, const char *jsonp, size_t jsonp_len); #endif diff --git a/formats/raw.c b/formats/raw.c index bb8f039..f8a1767 100644 --- a/formats/raw.c +++ b/formats/raw.c @@ -1,5 +1,4 @@ #include "raw.h" -#include "cmd.h" #include "common.h" #include "http.h" @@ -14,7 +13,7 @@ void raw_reply(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; - struct cmd *cmd = privdata; + struct http_client *client = privdata; char *raw_out; size_t sz; (void)c; @@ -26,7 +25,7 @@ raw_reply(redisAsyncContext *c, void *r, void *privdata) { raw_out = raw_wrap(r, &sz); /* send reply */ - format_send_reply(cmd, raw_out, sz, "binary/octet-stream"); + format_send_reply(client, raw_out, sz, "binary/octet-stream"); /* cleanup */ free(raw_out);