Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 237 lines (186 sloc) 4.617 kb
525c63d @nicolasff Added more msgpack support
authored
1 #include "msgpack.h"
2 #include "common.h"
3 #include "cmd.h"
4 #include "http.h"
5 #include "client.h"
6
7 #include <string.h>
8 #include <hiredis/hiredis.h>
9 #include <hiredis/async.h>
10
78932bf @nicolasff Working MessagePack implementation, if available.
authored
11 struct msg_out {
12 char *p;
13 size_t sz;
14 };
15
16 static void
17 msgpack_wrap_redis_reply(const struct cmd *cmd, struct msg_out *, const redisReply *r);
525c63d @nicolasff Added more msgpack support
authored
18
19 void
20 msgpack_reply(redisAsyncContext *c, void *r, void *privdata) {
21
22 redisReply *reply = r;
23 struct cmd *cmd = privdata;
78932bf @nicolasff Working MessagePack implementation, if available.
authored
24 struct msg_out out;
525c63d @nicolasff Added more msgpack support
authored
25 (void)c;
26
27 if(cmd == NULL) {
28 /* broken connection */
29 return;
30 }
31
32 if (reply == NULL) { /* broken Redis link */
33 format_send_error(cmd, 503, "Service Unavailable");
34 return;
35 }
36
78932bf @nicolasff Working MessagePack implementation, if available.
authored
37 /* prepare data structure for output */
38 out.p = NULL;
39 out.sz = 0;
525c63d @nicolasff Added more msgpack support
authored
40
78932bf @nicolasff Working MessagePack implementation, if available.
authored
41 /* encode redis reply */
42 msgpack_wrap_redis_reply(cmd, &out, r);
525c63d @nicolasff Added more msgpack support
authored
43
44 /* send reply */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
45 format_send_reply(cmd, out.p, out.sz, "application/x-msgpack");
525c63d @nicolasff Added more msgpack support
authored
46
47 /* cleanup */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
48 free(out.p);
49 }
50
51 static int
52 on_msgpack_write(void *data, const char *s, unsigned int sz) {
53
54 struct msg_out *out = data;
55
56 out->p = realloc(out->p, out->sz + sz);
57 memcpy(out->p + out->sz, s, sz);
58 out->sz += sz;
59
60 return sz;
525c63d @nicolasff Added more msgpack support
authored
61 }
62
63 /**
64 * Parse info message and return object.
65 */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
66 void
67 msg_info_reply(msgpack_packer* pk, const char *s, size_t sz) {
e676f59 @nicolasff MessagePack bugfixes
authored
68
525c63d @nicolasff Added more msgpack support
authored
69 const char *p = s;
78932bf @nicolasff Working MessagePack implementation, if available.
authored
70 unsigned int count = 0;
525c63d @nicolasff Added more msgpack support
authored
71
72 /* TODO: handle new format */
73
78932bf @nicolasff Working MessagePack implementation, if available.
authored
74 /* count number of lines */
75 while(p < s + sz) {
76 p = strchr(p, '\r');
77 if(!p) break;
78
79 p++;
80 count++;
81 }
82
83 /* create msgpack object */
84 msgpack_pack_map(pk, count);
85
86 p = s;
525c63d @nicolasff Added more msgpack support
authored
87 while(p < s + sz) {
88 char *key, *val, *nl, *colon;
78932bf @nicolasff Working MessagePack implementation, if available.
authored
89 size_t key_sz, val_sz;
525c63d @nicolasff Added more msgpack support
authored
90
91 /* find key */
92 colon = strchr(p, ':');
93 if(!colon) {
94 break;
95 }
78932bf @nicolasff Working MessagePack implementation, if available.
authored
96 key_sz = colon - p;
97 key = calloc(key_sz + 1, 1);
98 memcpy(key, p, key_sz);
525c63d @nicolasff Added more msgpack support
authored
99 p = colon + 1;
100
101 /* find value */
102 nl = strchr(p, '\r');
103 if(!nl) {
104 free(key);
105 break;
106 }
78932bf @nicolasff Working MessagePack implementation, if available.
authored
107 val_sz = nl - p;
108 val = calloc(val_sz + 1, 1);
109 memcpy(val, p, val_sz);
525c63d @nicolasff Added more msgpack support
authored
110 p = nl + 1;
111 if(*p == '\n') p++;
112
113 /* add to object */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
114 msgpack_pack_raw(pk, key_sz);
115 msgpack_pack_raw_body(pk, key, key_sz);
116 msgpack_pack_raw(pk, val_sz);
117 msgpack_pack_raw_body(pk, val, val_sz);
118
525c63d @nicolasff Added more msgpack support
authored
119 free(key);
120 free(val);
121 }
122 }
123
78932bf @nicolasff Working MessagePack implementation, if available.
authored
124 static void
125 msg_hgetall_reply(msgpack_packer* pk, const redisReply *r) {
e676f59 @nicolasff MessagePack bugfixes
authored
126
78932bf @nicolasff Working MessagePack implementation, if available.
authored
127 /* zip keys and values together in a msgpack object */
e676f59 @nicolasff MessagePack bugfixes
authored
128
525c63d @nicolasff Added more msgpack support
authored
129 unsigned int i;
130
131 if(r->elements % 2 != 0) {
78932bf @nicolasff Working MessagePack implementation, if available.
authored
132 return;
525c63d @nicolasff Added more msgpack support
authored
133 }
134
78932bf @nicolasff Working MessagePack implementation, if available.
authored
135 msgpack_pack_map(pk, r->elements / 2);
525c63d @nicolasff Added more msgpack support
authored
136 for(i = 0; i < r->elements; i += 2) {
137 redisReply *k = r->element[i], *v = r->element[i+1];
138
139 /* keys and values need to be strings */
140 if(k->type != REDIS_REPLY_STRING || v->type != REDIS_REPLY_STRING) {
78932bf @nicolasff Working MessagePack implementation, if available.
authored
141 return;
525c63d @nicolasff Added more msgpack support
authored
142 }
78932bf @nicolasff Working MessagePack implementation, if available.
authored
143
144 /* key */
145 msgpack_pack_raw(pk, k->len);
146 msgpack_pack_raw_body(pk, k->str, k->len);
147
148 /* value */
149 msgpack_pack_raw(pk, v->len);
150 msgpack_pack_raw_body(pk, v->str, v->len);
525c63d @nicolasff Added more msgpack support
authored
151 }
152 }
153
78932bf @nicolasff Working MessagePack implementation, if available.
authored
154 static void
155 msgpack_wrap_redis_reply(const struct cmd *cmd, struct msg_out *out, const redisReply *r) {
525c63d @nicolasff Added more msgpack support
authored
156
157 unsigned int i;
78932bf @nicolasff Working MessagePack implementation, if available.
authored
158 msgpack_packer* pk = msgpack_packer_new(out, on_msgpack_write);
525c63d @nicolasff Added more msgpack support
authored
159
160 /* copy verb, as jansson only takes a char* but not its length. */
e676f59 @nicolasff MessagePack bugfixes
authored
161 char *verb = "";
78932bf @nicolasff Working MessagePack implementation, if available.
authored
162 size_t verb_sz = 0;
525c63d @nicolasff Added more msgpack support
authored
163 if(cmd->count) {
78932bf @nicolasff Working MessagePack implementation, if available.
authored
164 verb_sz = cmd->argv_len[0];
e676f59 @nicolasff MessagePack bugfixes
authored
165 verb = cmd->argv[0];
525c63d @nicolasff Added more msgpack support
authored
166 }
167
e676f59 @nicolasff MessagePack bugfixes
authored
168 /* Create map object */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
169 msgpack_pack_map(pk, 1);
170
e676f59 @nicolasff MessagePack bugfixes
authored
171 /* The single element is the verb */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
172 msgpack_pack_raw(pk, verb_sz);
173 msgpack_pack_raw_body(pk, verb, verb_sz);
525c63d @nicolasff Added more msgpack support
authored
174
175 switch(r->type) {
176 case REDIS_REPLY_STATUS:
177 case REDIS_REPLY_ERROR:
1cd5761 @nicolasff Added MessagePack tests and fixed status reply
authored
178 msgpack_pack_array(pk, 2);
78932bf @nicolasff Working MessagePack implementation, if available.
authored
179
1cd5761 @nicolasff Added MessagePack tests and fixed status reply
authored
180 /* first element: book */
78932bf @nicolasff Working MessagePack implementation, if available.
authored
181 if(r->type == REDIS_REPLY_ERROR)
182 msgpack_pack_false(pk);
183 else
184 msgpack_pack_true(pk);
1cd5761 @nicolasff Added MessagePack tests and fixed status reply
authored
185
186 /* second element: message */
187 msgpack_pack_raw(pk, r->len);
188 msgpack_pack_raw_body(pk, r->str, r->len);
525c63d @nicolasff Added more msgpack support
authored
189 break;
190
191 case REDIS_REPLY_STRING:
e676f59 @nicolasff MessagePack bugfixes
authored
192 if(verb_sz ==4 && strncasecmp(verb, "INFO", 4) == 0) {
78932bf @nicolasff Working MessagePack implementation, if available.
authored
193 msg_info_reply(pk, r->str, r->len);
525c63d @nicolasff Added more msgpack support
authored
194 } else {
78932bf @nicolasff Working MessagePack implementation, if available.
authored
195 msgpack_pack_raw(pk, r->len);
196 msgpack_pack_raw_body(pk, r->str, r->len);
525c63d @nicolasff Added more msgpack support
authored
197 }
198 break;
199
200 case REDIS_REPLY_INTEGER:
e676f59 @nicolasff MessagePack bugfixes
authored
201 msgpack_pack_int(pk, r->integer);
525c63d @nicolasff Added more msgpack support
authored
202 break;
203
204 case REDIS_REPLY_ARRAY:
e676f59 @nicolasff MessagePack bugfixes
authored
205 if(verb_sz == 7 && strncasecmp(verb, "HGETALL", 7) == 0) {
78932bf @nicolasff Working MessagePack implementation, if available.
authored
206 msg_hgetall_reply(pk, r);
207 break;
525c63d @nicolasff Added more msgpack support
authored
208 }
78932bf @nicolasff Working MessagePack implementation, if available.
authored
209
210 msgpack_pack_array(pk, r->elements);
211
525c63d @nicolasff Added more msgpack support
authored
212 for(i = 0; i < r->elements; ++i) {
213 redisReply *e = r->element[i];
214 switch(e->type) {
215 case REDIS_REPLY_STRING:
78932bf @nicolasff Working MessagePack implementation, if available.
authored
216 msgpack_pack_raw(pk, e->len);
217 msgpack_pack_raw_body(pk, e->str, e->len);
525c63d @nicolasff Added more msgpack support
authored
218 break;
219 case REDIS_REPLY_INTEGER:
e676f59 @nicolasff MessagePack bugfixes
authored
220 msgpack_pack_int(pk, e->integer);
525c63d @nicolasff Added more msgpack support
authored
221 break;
222 default:
78932bf @nicolasff Working MessagePack implementation, if available.
authored
223 msgpack_pack_nil(pk);
525c63d @nicolasff Added more msgpack support
authored
224 break;
225 }
226 }
78932bf @nicolasff Working MessagePack implementation, if available.
authored
227
525c63d @nicolasff Added more msgpack support
authored
228 break;
229
230 default:
78932bf @nicolasff Working MessagePack implementation, if available.
authored
231 msgpack_pack_nil(pk);
525c63d @nicolasff Added more msgpack support
authored
232 break;
233 }
234
78932bf @nicolasff Working MessagePack implementation, if available.
authored
235 msgpack_packer_free(pk);
525c63d @nicolasff Added more msgpack support
authored
236 }
Something went wrong with that request. Please try again.