redis-client 0.3.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile +1 -2
  4. data/Gemfile.lock +1 -2
  5. data/README.md +13 -17
  6. data/Rakefile +41 -22
  7. data/lib/redis_client/command_builder.rb +8 -0
  8. data/lib/redis_client/config.rb +13 -5
  9. data/lib/redis_client/connection_mixin.rb +2 -0
  10. data/lib/redis_client/version.rb +1 -1
  11. data/lib/redis_client.rb +31 -15
  12. data/redis-client.gemspec +2 -4
  13. metadata +6 -56
  14. data/.rubocop.yml +0 -191
  15. data/ext/redis_client/hiredis/export.clang +0 -2
  16. data/ext/redis_client/hiredis/export.gcc +0 -7
  17. data/ext/redis_client/hiredis/extconf.rb +0 -69
  18. data/ext/redis_client/hiredis/hiredis_connection.c +0 -708
  19. data/ext/redis_client/hiredis/vendor/.gitignore +0 -9
  20. data/ext/redis_client/hiredis/vendor/.travis.yml +0 -131
  21. data/ext/redis_client/hiredis/vendor/CHANGELOG.md +0 -364
  22. data/ext/redis_client/hiredis/vendor/CMakeLists.txt +0 -165
  23. data/ext/redis_client/hiredis/vendor/COPYING +0 -29
  24. data/ext/redis_client/hiredis/vendor/Makefile +0 -308
  25. data/ext/redis_client/hiredis/vendor/README.md +0 -664
  26. data/ext/redis_client/hiredis/vendor/adapters/ae.h +0 -130
  27. data/ext/redis_client/hiredis/vendor/adapters/glib.h +0 -156
  28. data/ext/redis_client/hiredis/vendor/adapters/ivykis.h +0 -84
  29. data/ext/redis_client/hiredis/vendor/adapters/libev.h +0 -179
  30. data/ext/redis_client/hiredis/vendor/adapters/libevent.h +0 -175
  31. data/ext/redis_client/hiredis/vendor/adapters/libuv.h +0 -117
  32. data/ext/redis_client/hiredis/vendor/adapters/macosx.h +0 -115
  33. data/ext/redis_client/hiredis/vendor/adapters/qt.h +0 -135
  34. data/ext/redis_client/hiredis/vendor/alloc.c +0 -86
  35. data/ext/redis_client/hiredis/vendor/alloc.h +0 -91
  36. data/ext/redis_client/hiredis/vendor/appveyor.yml +0 -24
  37. data/ext/redis_client/hiredis/vendor/async.c +0 -887
  38. data/ext/redis_client/hiredis/vendor/async.h +0 -147
  39. data/ext/redis_client/hiredis/vendor/async_private.h +0 -75
  40. data/ext/redis_client/hiredis/vendor/dict.c +0 -352
  41. data/ext/redis_client/hiredis/vendor/dict.h +0 -126
  42. data/ext/redis_client/hiredis/vendor/fmacros.h +0 -12
  43. data/ext/redis_client/hiredis/vendor/hiredis-config.cmake.in +0 -13
  44. data/ext/redis_client/hiredis/vendor/hiredis.c +0 -1174
  45. data/ext/redis_client/hiredis/vendor/hiredis.h +0 -336
  46. data/ext/redis_client/hiredis/vendor/hiredis.pc.in +0 -12
  47. data/ext/redis_client/hiredis/vendor/hiredis_ssl-config.cmake.in +0 -13
  48. data/ext/redis_client/hiredis/vendor/hiredis_ssl.h +0 -157
  49. data/ext/redis_client/hiredis/vendor/hiredis_ssl.pc.in +0 -12
  50. data/ext/redis_client/hiredis/vendor/net.c +0 -612
  51. data/ext/redis_client/hiredis/vendor/net.h +0 -56
  52. data/ext/redis_client/hiredis/vendor/read.c +0 -739
  53. data/ext/redis_client/hiredis/vendor/read.h +0 -129
  54. data/ext/redis_client/hiredis/vendor/sds.c +0 -1289
  55. data/ext/redis_client/hiredis/vendor/sds.h +0 -278
  56. data/ext/redis_client/hiredis/vendor/sdsalloc.h +0 -44
  57. data/ext/redis_client/hiredis/vendor/sockcompat.c +0 -248
  58. data/ext/redis_client/hiredis/vendor/sockcompat.h +0 -92
  59. data/ext/redis_client/hiredis/vendor/ssl.c +0 -544
  60. data/ext/redis_client/hiredis/vendor/test.c +0 -1401
  61. data/ext/redis_client/hiredis/vendor/test.sh +0 -78
  62. data/ext/redis_client/hiredis/vendor/win32.h +0 -56
  63. data/lib/redis_client/hiredis_connection.rb +0 -93
@@ -1,664 +0,0 @@
1
- [![Build Status](https://travis-ci.org/redis/hiredis.png)](https://travis-ci.org/redis/hiredis)
2
-
3
- **This Readme reflects the latest changed in the master branch. See [v1.0.0](https://github.com/redis/hiredis/tree/v1.0.0) for the Readme and documentation for the latest release ([API/ABI history](https://abi-laboratory.pro/?view=timeline&l=hiredis)).**
4
-
5
- # HIREDIS
6
-
7
- Hiredis is a minimalistic C client library for the [Redis](http://redis.io/) database.
8
-
9
- It is minimalistic because it just adds minimal support for the protocol, but
10
- at the same time it uses a high level printf-alike API in order to make it
11
- much higher level than otherwise suggested by its minimal code base and the
12
- lack of explicit bindings for every Redis command.
13
-
14
- Apart from supporting sending commands and receiving replies, it comes with
15
- a reply parser that is decoupled from the I/O layer. It
16
- is a stream parser designed for easy reusability, which can for instance be used
17
- in higher level language bindings for efficient reply parsing.
18
-
19
- Hiredis only supports the binary-safe Redis protocol, so you can use it with any
20
- Redis version >= 1.2.0.
21
-
22
- The library comes with multiple APIs. There is the
23
- *synchronous API*, the *asynchronous API* and the *reply parsing API*.
24
-
25
- ## Upgrading to `1.0.2`
26
-
27
- <span style="color:red">NOTE: v1.0.1 erroneously bumped SONAME, which is why it is skipped here.</span>
28
-
29
- Version 1.0.2 is simply 1.0.0 with a fix for [CVE-2021-32765](https://github.com/redis/hiredis/security/advisories/GHSA-hfm9-39pp-55p2). They are otherwise identical.
30
-
31
- ## Upgrading to `1.0.0`
32
-
33
- Version 1.0.0 marks the first stable release of Hiredis.
34
- It includes some minor breaking changes, mostly to make the exposed API more uniform and self-explanatory.
35
- It also bundles the updated `sds` library, to sync up with upstream and Redis.
36
- For code changes see the [Changelog](CHANGELOG.md).
37
-
38
- _Note: As described below, a few member names have been changed but most applications should be able to upgrade with minor code changes and recompiling._
39
-
40
- ## IMPORTANT: Breaking changes from `0.14.1` -> `1.0.0`
41
-
42
- * `redisContext` has two additional members (`free_privdata`, and `privctx`).
43
- * `redisOptions.timeout` has been renamed to `redisOptions.connect_timeout`, and we've added `redisOptions.command_timeout`.
44
- * `redisReplyObjectFunctions.createArray` now takes `size_t` instead of `int` for its length parameter.
45
-
46
- ## IMPORTANT: Breaking changes when upgrading from 0.13.x -> 0.14.x
47
-
48
- Bulk and multi-bulk lengths less than -1 or greater than `LLONG_MAX` are now
49
- protocol errors. This is consistent with the RESP specification. On 32-bit
50
- platforms, the upper bound is lowered to `SIZE_MAX`.
51
-
52
- Change `redisReply.len` to `size_t`, as it denotes the the size of a string
53
-
54
- User code should compare this to `size_t` values as well. If it was used to
55
- compare to other values, casting might be necessary or can be removed, if
56
- casting was applied before.
57
-
58
- ## Upgrading from `<0.9.0`
59
-
60
- Version 0.9.0 is a major overhaul of hiredis in every aspect. However, upgrading existing
61
- code using hiredis should not be a big pain. The key thing to keep in mind when
62
- upgrading is that hiredis >= 0.9.0 uses a `redisContext*` to keep state, in contrast to
63
- the stateless 0.0.1 that only has a file descriptor to work with.
64
-
65
- ## Synchronous API
66
-
67
- To consume the synchronous API, there are only a few function calls that need to be introduced:
68
-
69
- ```c
70
- redisContext *redisConnect(const char *ip, int port);
71
- void *redisCommand(redisContext *c, const char *format, ...);
72
- void freeReplyObject(void *reply);
73
- ```
74
-
75
- ### Connecting
76
-
77
- The function `redisConnect` is used to create a so-called `redisContext`. The
78
- context is where Hiredis holds state for a connection. The `redisContext`
79
- struct has an integer `err` field that is non-zero when the connection is in
80
- an error state. The field `errstr` will contain a string with a description of
81
- the error. More information on errors can be found in the **Errors** section.
82
- After trying to connect to Redis using `redisConnect` you should
83
- check the `err` field to see if establishing the connection was successful:
84
- ```c
85
- redisContext *c = redisConnect("127.0.0.1", 6379);
86
- if (c == NULL || c->err) {
87
- if (c) {
88
- printf("Error: %s\n", c->errstr);
89
- // handle error
90
- } else {
91
- printf("Can't allocate redis context\n");
92
- }
93
- }
94
- ```
95
-
96
- *Note: A `redisContext` is not thread-safe.*
97
-
98
- ### Sending commands
99
-
100
- There are several ways to issue commands to Redis. The first that will be introduced is
101
- `redisCommand`. This function takes a format similar to printf. In the simplest form,
102
- it is used like this:
103
- ```c
104
- reply = redisCommand(context, "SET foo bar");
105
- ```
106
-
107
- The specifier `%s` interpolates a string in the command, and uses `strlen` to
108
- determine the length of the string:
109
- ```c
110
- reply = redisCommand(context, "SET foo %s", value);
111
- ```
112
- When you need to pass binary safe strings in a command, the `%b` specifier can be
113
- used. Together with a pointer to the string, it requires a `size_t` length argument
114
- of the string:
115
- ```c
116
- reply = redisCommand(context, "SET foo %b", value, (size_t) valuelen);
117
- ```
118
- Internally, Hiredis splits the command in different arguments and will
119
- convert it to the protocol used to communicate with Redis.
120
- One or more spaces separates arguments, so you can use the specifiers
121
- anywhere in an argument:
122
- ```c
123
- reply = redisCommand(context, "SET key:%s %s", myid, value);
124
- ```
125
-
126
- ### Using replies
127
-
128
- The return value of `redisCommand` holds a reply when the command was
129
- successfully executed. When an error occurs, the return value is `NULL` and
130
- the `err` field in the context will be set (see section on **Errors**).
131
- Once an error is returned the context cannot be reused and you should set up
132
- a new connection.
133
-
134
- The standard replies that `redisCommand` are of the type `redisReply`. The
135
- `type` field in the `redisReply` should be used to test what kind of reply
136
- was received:
137
-
138
- ### RESP2
139
-
140
- * **`REDIS_REPLY_STATUS`**:
141
- * The command replied with a status reply. The status string can be accessed using `reply->str`.
142
- The length of this string can be accessed using `reply->len`.
143
-
144
- * **`REDIS_REPLY_ERROR`**:
145
- * The command replied with an error. The error string can be accessed identical to `REDIS_REPLY_STATUS`.
146
-
147
- * **`REDIS_REPLY_INTEGER`**:
148
- * The command replied with an integer. The integer value can be accessed using the
149
- `reply->integer` field of type `long long`.
150
-
151
- * **`REDIS_REPLY_NIL`**:
152
- * The command replied with a **nil** object. There is no data to access.
153
-
154
- * **`REDIS_REPLY_STRING`**:
155
- * A bulk (string) reply. The value of the reply can be accessed using `reply->str`.
156
- The length of this string can be accessed using `reply->len`.
157
-
158
- * **`REDIS_REPLY_ARRAY`**:
159
- * A multi bulk reply. The number of elements in the multi bulk reply is stored in
160
- `reply->elements`. Every element in the multi bulk reply is a `redisReply` object as well
161
- and can be accessed via `reply->element[..index..]`.
162
- Redis may reply with nested arrays but this is fully supported.
163
-
164
- ### RESP3
165
-
166
- Hiredis also supports every new `RESP3` data type which are as follows. For more information about the protocol see the `RESP3` [specification.](https://github.com/antirez/RESP3/blob/master/spec.md)
167
-
168
- * **`REDIS_REPLY_DOUBLE`**:
169
- * The command replied with a double-precision floating point number.
170
- The value is stored as a string in the `str` member, and can be converted with `strtod` or similar.
171
-
172
- * **`REDIS_REPLY_BOOL`**:
173
- * A boolean true/false reply.
174
- The value is stored in the `integer` member and will be either `0` or `1`.
175
-
176
- * **`REDIS_REPLY_MAP`**:
177
- * An array with the added invariant that there will always be an even number of elements.
178
- The MAP is functionally equivelant to `REDIS_REPLY_ARRAY` except for the previously mentioned invariant.
179
-
180
- * **`REDIS_REPLY_SET`**:
181
- * An array response where each entry is unique.
182
- Like the MAP type, the data is identical to an array response except there are no duplicate values.
183
-
184
- * **`REDIS_REPLY_PUSH`**:
185
- * An array that can be generated spontaneously by Redis.
186
- This array response will always contain at least two subelements. The first contains the type of `PUSH` message (e.g. `message`, or `invalidate`), and the second being a sub-array with the `PUSH` payload itself.
187
-
188
- * **`REDIS_REPLY_ATTR`**:
189
- * An array structurally identical to a `MAP` but intended as meta-data about a reply.
190
- _As of Redis 6.0.6 this reply type is not used in Redis_
191
-
192
- * **`REDIS_REPLY_BIGNUM`**:
193
- * A string representing an arbitrarily large signed or unsigned integer value.
194
- The number will be encoded as a string in the `str` member of `redisReply`.
195
-
196
- * **`REDIS_REPLY_VERB`**:
197
- * A verbatim string, intended to be presented to the user without modification.
198
- The string payload is stored in the `str` memeber, and type data is stored in the `vtype` member (e.g. `txt` for raw text or `md` for markdown).
199
-
200
- Replies should be freed using the `freeReplyObject()` function.
201
- Note that this function will take care of freeing sub-reply objects
202
- contained in arrays and nested arrays, so there is no need for the user to
203
- free the sub replies (it is actually harmful and will corrupt the memory).
204
-
205
- **Important:** the current version of hiredis (1.0.0) frees replies when the
206
- asynchronous API is used. This means you should not call `freeReplyObject` when
207
- you use this API. The reply is cleaned up by hiredis _after_ the callback
208
- returns. We may introduce a flag to make this configurable in future versions of the library.
209
-
210
- ### Cleaning up
211
-
212
- To disconnect and free the context the following function can be used:
213
- ```c
214
- void redisFree(redisContext *c);
215
- ```
216
- This function immediately closes the socket and then frees the allocations done in
217
- creating the context.
218
-
219
- ### Sending commands (cont'd)
220
-
221
- Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.
222
- It has the following prototype:
223
- ```c
224
- void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
225
- ```
226
- It takes the number of arguments `argc`, an array of strings `argv` and the lengths of the
227
- arguments `argvlen`. For convenience, `argvlen` may be set to `NULL` and the function will
228
- use `strlen(3)` on every argument to determine its length. Obviously, when any of the arguments
229
- need to be binary safe, the entire array of lengths `argvlen` should be provided.
230
-
231
- The return value has the same semantic as `redisCommand`.
232
-
233
- ### Pipelining
234
-
235
- To explain how Hiredis supports pipelining in a blocking connection, there needs to be
236
- understanding of the internal execution flow.
237
-
238
- When any of the functions in the `redisCommand` family is called, Hiredis first formats the
239
- command according to the Redis protocol. The formatted command is then put in the output buffer
240
- of the context. This output buffer is dynamic, so it can hold any number of commands.
241
- After the command is put in the output buffer, `redisGetReply` is called. This function has the
242
- following two execution paths:
243
-
244
- 1. The input buffer is non-empty:
245
- * Try to parse a single reply from the input buffer and return it
246
- * If no reply could be parsed, continue at *2*
247
- 2. The input buffer is empty:
248
- * Write the **entire** output buffer to the socket
249
- * Read from the socket until a single reply could be parsed
250
-
251
- The function `redisGetReply` is exported as part of the Hiredis API and can be used when a reply
252
- is expected on the socket. To pipeline commands, the only things that needs to be done is
253
- filling up the output buffer. For this cause, two commands can be used that are identical
254
- to the `redisCommand` family, apart from not returning a reply:
255
- ```c
256
- void redisAppendCommand(redisContext *c, const char *format, ...);
257
- void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
258
- ```
259
- After calling either function one or more times, `redisGetReply` can be used to receive the
260
- subsequent replies. The return value for this function is either `REDIS_OK` or `REDIS_ERR`, where
261
- the latter means an error occurred while reading a reply. Just as with the other commands,
262
- the `err` field in the context can be used to find out what the cause of this error is.
263
-
264
- The following examples shows a simple pipeline (resulting in only a single call to `write(2)` and
265
- a single call to `read(2)`):
266
- ```c
267
- redisReply *reply;
268
- redisAppendCommand(context,"SET foo bar");
269
- redisAppendCommand(context,"GET foo");
270
- redisGetReply(context,(void *)&reply); // reply for SET
271
- freeReplyObject(reply);
272
- redisGetReply(context,(void *)&reply); // reply for GET
273
- freeReplyObject(reply);
274
- ```
275
- This API can also be used to implement a blocking subscriber:
276
- ```c
277
- reply = redisCommand(context,"SUBSCRIBE foo");
278
- freeReplyObject(reply);
279
- while(redisGetReply(context,(void *)&reply) == REDIS_OK) {
280
- // consume message
281
- freeReplyObject(reply);
282
- }
283
- ```
284
- ### Errors
285
-
286
- When a function call is not successful, depending on the function either `NULL` or `REDIS_ERR` is
287
- returned. The `err` field inside the context will be non-zero and set to one of the
288
- following constants:
289
-
290
- * **`REDIS_ERR_IO`**:
291
- There was an I/O error while creating the connection, trying to write
292
- to the socket or read from the socket. If you included `errno.h` in your
293
- application, you can use the global `errno` variable to find out what is
294
- wrong.
295
-
296
- * **`REDIS_ERR_EOF`**:
297
- The server closed the connection which resulted in an empty read.
298
-
299
- * **`REDIS_ERR_PROTOCOL`**:
300
- There was an error while parsing the protocol.
301
-
302
- * **`REDIS_ERR_OTHER`**:
303
- Any other error. Currently, it is only used when a specified hostname to connect
304
- to cannot be resolved.
305
-
306
- In every case, the `errstr` field in the context will be set to hold a string representation
307
- of the error.
308
-
309
- ## Asynchronous API
310
-
311
- Hiredis comes with an asynchronous API that works easily with any event library.
312
- Examples are bundled that show using Hiredis with [libev](http://software.schmorp.de/pkg/libev.html)
313
- and [libevent](http://monkey.org/~provos/libevent/).
314
-
315
- ### Connecting
316
-
317
- The function `redisAsyncConnect` can be used to establish a non-blocking connection to
318
- Redis. It returns a pointer to the newly created `redisAsyncContext` struct. The `err` field
319
- should be checked after creation to see if there were errors creating the connection.
320
- Because the connection that will be created is non-blocking, the kernel is not able to
321
- instantly return if the specified host and port is able to accept a connection.
322
-
323
- *Note: A `redisAsyncContext` is not thread-safe.*
324
-
325
- ```c
326
- redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
327
- if (c->err) {
328
- printf("Error: %s\n", c->errstr);
329
- // handle error
330
- }
331
- ```
332
-
333
- The asynchronous context can hold a disconnect callback function that is called when the
334
- connection is disconnected (either because of an error or per user request). This function should
335
- have the following prototype:
336
- ```c
337
- void(const redisAsyncContext *c, int status);
338
- ```
339
- On a disconnect, the `status` argument is set to `REDIS_OK` when disconnection was initiated by the
340
- user, or `REDIS_ERR` when the disconnection was caused by an error. When it is `REDIS_ERR`, the `err`
341
- field in the context can be accessed to find out the cause of the error.
342
-
343
- The context object is always freed after the disconnect callback fired. When a reconnect is needed,
344
- the disconnect callback is a good point to do so.
345
-
346
- Setting the disconnect callback can only be done once per context. For subsequent calls it will
347
- return `REDIS_ERR`. The function to set the disconnect callback has the following prototype:
348
- ```c
349
- int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
350
- ```
351
- `ac->data` may be used to pass user data to this callback, the same can be done for redisConnectCallback.
352
- ### Sending commands and their callbacks
353
-
354
- In an asynchronous context, commands are automatically pipelined due to the nature of an event loop.
355
- Therefore, unlike the synchronous API, there is only a single way to send commands.
356
- Because commands are sent to Redis asynchronously, issuing a command requires a callback function
357
- that is called when the reply is received. Reply callbacks should have the following prototype:
358
- ```c
359
- void(redisAsyncContext *c, void *reply, void *privdata);
360
- ```
361
- The `privdata` argument can be used to curry arbitrary data to the callback from the point where
362
- the command is initially queued for execution.
363
-
364
- The functions that can be used to issue commands in an asynchronous context are:
365
- ```c
366
- int redisAsyncCommand(
367
- redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
368
- const char *format, ...);
369
- int redisAsyncCommandArgv(
370
- redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
371
- int argc, const char **argv, const size_t *argvlen);
372
- ```
373
- Both functions work like their blocking counterparts. The return value is `REDIS_OK` when the command
374
- was successfully added to the output buffer and `REDIS_ERR` otherwise. Example: when the connection
375
- is being disconnected per user-request, no new commands may be added to the output buffer and `REDIS_ERR` is
376
- returned on calls to the `redisAsyncCommand` family.
377
-
378
- If the reply for a command with a `NULL` callback is read, it is immediately freed. When the callback
379
- for a command is non-`NULL`, the memory is freed immediately following the callback: the reply is only
380
- valid for the duration of the callback.
381
-
382
- All pending callbacks are called with a `NULL` reply when the context encountered an error.
383
-
384
- ### Disconnecting
385
-
386
- An asynchronous connection can be terminated using:
387
- ```c
388
- void redisAsyncDisconnect(redisAsyncContext *ac);
389
- ```
390
- When this function is called, the connection is **not** immediately terminated. Instead, new
391
- commands are no longer accepted and the connection is only terminated when all pending commands
392
- have been written to the socket, their respective replies have been read and their respective
393
- callbacks have been executed. After this, the disconnection callback is executed with the
394
- `REDIS_OK` status and the context object is freed.
395
-
396
- ### Hooking it up to event library *X*
397
-
398
- There are a few hooks that need to be set on the context object after it is created.
399
- See the `adapters/` directory for bindings to *libev* and *libevent*.
400
-
401
- ## Reply parsing API
402
-
403
- Hiredis comes with a reply parsing API that makes it easy for writing higher
404
- level language bindings.
405
-
406
- The reply parsing API consists of the following functions:
407
- ```c
408
- redisReader *redisReaderCreate(void);
409
- void redisReaderFree(redisReader *reader);
410
- int redisReaderFeed(redisReader *reader, const char *buf, size_t len);
411
- int redisReaderGetReply(redisReader *reader, void **reply);
412
- ```
413
- The same set of functions are used internally by hiredis when creating a
414
- normal Redis context, the above API just exposes it to the user for a direct
415
- usage.
416
-
417
- ### Usage
418
-
419
- The function `redisReaderCreate` creates a `redisReader` structure that holds a
420
- buffer with unparsed data and state for the protocol parser.
421
-
422
- Incoming data -- most likely from a socket -- can be placed in the internal
423
- buffer of the `redisReader` using `redisReaderFeed`. This function will make a
424
- copy of the buffer pointed to by `buf` for `len` bytes. This data is parsed
425
- when `redisReaderGetReply` is called. This function returns an integer status
426
- and a reply object (as described above) via `void **reply`. The returned status
427
- can be either `REDIS_OK` or `REDIS_ERR`, where the latter means something went
428
- wrong (either a protocol error, or an out of memory error).
429
-
430
- The parser limits the level of nesting for multi bulk payloads to 7. If the
431
- multi bulk nesting level is higher than this, the parser returns an error.
432
-
433
- ### Customizing replies
434
-
435
- The function `redisReaderGetReply` creates `redisReply` and makes the function
436
- argument `reply` point to the created `redisReply` variable. For instance, if
437
- the response of type `REDIS_REPLY_STATUS` then the `str` field of `redisReply`
438
- will hold the status as a vanilla C string. However, the functions that are
439
- responsible for creating instances of the `redisReply` can be customized by
440
- setting the `fn` field on the `redisReader` struct. This should be done
441
- immediately after creating the `redisReader`.
442
-
443
- For example, [hiredis-rb](https://github.com/pietern/hiredis-rb/blob/master/ext/hiredis_ext/reader.c)
444
- uses customized reply object functions to create Ruby objects.
445
-
446
- ### Reader max buffer
447
-
448
- Both when using the Reader API directly or when using it indirectly via a
449
- normal Redis context, the redisReader structure uses a buffer in order to
450
- accumulate data from the server.
451
- Usually this buffer is destroyed when it is empty and is larger than 16
452
- KiB in order to avoid wasting memory in unused buffers
453
-
454
- However when working with very big payloads destroying the buffer may slow
455
- down performances considerably, so it is possible to modify the max size of
456
- an idle buffer changing the value of the `maxbuf` field of the reader structure
457
- to the desired value. The special value of 0 means that there is no maximum
458
- value for an idle buffer, so the buffer will never get freed.
459
-
460
- For instance if you have a normal Redis context you can set the maximum idle
461
- buffer to zero (unlimited) just with:
462
- ```c
463
- context->reader->maxbuf = 0;
464
- ```
465
- This should be done only in order to maximize performances when working with
466
- large payloads. The context should be set back to `REDIS_READER_MAX_BUF` again
467
- as soon as possible in order to prevent allocation of useless memory.
468
-
469
- ### Reader max array elements
470
-
471
- By default the hiredis reply parser sets the maximum number of multi-bulk elements
472
- to 2^32 - 1 or 4,294,967,295 entries. If you need to process multi-bulk replies
473
- with more than this many elements you can set the value higher or to zero, meaning
474
- unlimited with:
475
- ```c
476
- context->reader->maxelements = 0;
477
- ```
478
-
479
- ## SSL/TLS Support
480
-
481
- ### Building
482
-
483
- SSL/TLS support is not built by default and requires an explicit flag:
484
-
485
- make USE_SSL=1
486
-
487
- This requires OpenSSL development package (e.g. including header files to be
488
- available.
489
-
490
- When enabled, SSL/TLS support is built into extra `libhiredis_ssl.a` and
491
- `libhiredis_ssl.so` static/dynamic libraries. This leaves the original libraries
492
- unaffected so no additional dependencies are introduced.
493
-
494
- ### Using it
495
-
496
- First, you'll need to make sure you include the SSL header file:
497
-
498
- ```c
499
- #include "hiredis.h"
500
- #include "hiredis_ssl.h"
501
- ```
502
-
503
- You will also need to link against `libhiredis_ssl`, **in addition** to
504
- `libhiredis` and add `-lssl -lcrypto` to satisfy its dependencies.
505
-
506
- Hiredis implements SSL/TLS on top of its normal `redisContext` or
507
- `redisAsyncContext`, so you will need to establish a connection first and then
508
- initiate an SSL/TLS handshake.
509
-
510
- #### Hiredis OpenSSL Wrappers
511
-
512
- Before Hiredis can negotiate an SSL/TLS connection, it is necessary to
513
- initialize OpenSSL and create a context. You can do that in two ways:
514
-
515
- 1. Work directly with the OpenSSL API to initialize the library's global context
516
- and create `SSL_CTX *` and `SSL *` contexts. With an `SSL *` object you can
517
- call `redisInitiateSSL()`.
518
- 2. Work with a set of Hiredis-provided wrappers around OpenSSL, create a
519
- `redisSSLContext` object to hold configuration and use
520
- `redisInitiateSSLWithContext()` to initiate the SSL/TLS handshake.
521
-
522
- ```c
523
- /* An Hiredis SSL context. It holds SSL configuration and can be reused across
524
- * many contexts.
525
- */
526
- redisSSLContext *ssl;
527
-
528
- /* An error variable to indicate what went wrong, if the context fails to
529
- * initialize.
530
- */
531
- redisSSLContextError ssl_error;
532
-
533
- /* Initialize global OpenSSL state.
534
- *
535
- * You should call this only once when your app initializes, and only if
536
- * you don't explicitly or implicitly initialize OpenSSL it elsewhere.
537
- */
538
- redisInitOpenSSL();
539
-
540
- /* Create SSL context */
541
- ssl = redisCreateSSLContext(
542
- "cacertbundle.crt", /* File name of trusted CA/ca bundle file, optional */
543
- "/path/to/certs", /* Path of trusted certificates, optional */
544
- "client_cert.pem", /* File name of client certificate file, optional */
545
- "client_key.pem", /* File name of client private key, optional */
546
- "redis.mydomain.com", /* Server name to request (SNI), optional */
547
- &ssl_error
548
- ) != REDIS_OK) {
549
- printf("SSL error: %s\n", redisSSLContextGetError(ssl_error);
550
- /* Abort... */
551
- }
552
-
553
- /* Create Redis context and establish connection */
554
- c = redisConnect("localhost", 6443);
555
- if (c == NULL || c->err) {
556
- /* Handle error and abort... */
557
- }
558
-
559
- /* Negotiate SSL/TLS */
560
- if (redisInitiateSSLWithContext(c, ssl) != REDIS_OK) {
561
- /* Handle error, in c->err / c->errstr */
562
- }
563
- ```
564
-
565
- ## RESP3 PUSH replies
566
- Redis 6.0 introduced PUSH replies with the reply-type `>`. These messages are generated spontaneously and can arrive at any time, so must be handled using callbacks.
567
-
568
- ### Default behavior
569
- Hiredis installs handlers on `redisContext` and `redisAsyncContext` by default, which will intercept and free any PUSH replies detected. This means existing code will work as-is after upgrading to Redis 6 and switching to `RESP3`.
570
-
571
- ### Custom PUSH handler prototypes
572
- The callback prototypes differ between `redisContext` and `redisAsyncContext`.
573
-
574
- #### redisContext
575
- ```c
576
- void my_push_handler(void *privdata, void *reply) {
577
- /* Handle the reply */
578
-
579
- /* Note: We need to free the reply in our custom handler for
580
- blocking contexts. This lets us keep the reply if
581
- we want. */
582
- freeReplyObject(reply);
583
- }
584
- ```
585
-
586
- #### redisAsyncContext
587
- ```c
588
- void my_async_push_handler(redisAsyncContext *ac, void *reply) {
589
- /* Handle the reply */
590
-
591
- /* Note: Because async hiredis always frees replies, you should
592
- not call freeReplyObject in an async push callback. */
593
- }
594
- ```
595
-
596
- ### Installing a custom handler
597
- There are two ways to set your own PUSH handlers.
598
-
599
- 1. Set `push_cb` or `async_push_cb` in the `redisOptions` struct and connect with `redisConnectWithOptions` or `redisAsyncConnectWithOptions`.
600
- ```c
601
- redisOptions = {0};
602
- REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379);
603
- options->push_cb = my_push_handler;
604
- redisContext *context = redisConnectWithOptions(&options);
605
- ```
606
- 2. Call `redisSetPushCallback` or `redisAsyncSetPushCallback` on a connected context.
607
- ```c
608
- redisContext *context = redisConnect("127.0.0.1", 6379);
609
- redisSetPushCallback(context, my_push_handler);
610
- ```
611
-
612
- _Note `redisSetPushCallback` and `redisAsyncSetPushCallback` both return any currently configured handler, making it easy to override and then return to the old value._
613
-
614
- ### Specifying no handler
615
- If you have a unique use-case where you don't want hiredis to automatically intercept and free PUSH replies, you will want to configure no handler at all. This can be done in two ways.
616
- 1. Set the `REDIS_OPT_NO_PUSH_AUTOFREE` flag in `redisOptions` and leave the callback function pointer `NULL`.
617
- ```c
618
- redisOptions = {0};
619
- REDIS_OPTIONS_SET_TCP(&options, "127.0.0.1", 6379);
620
- options->options |= REDIS_OPT_NO_PUSH_AUTOFREE;
621
- redisContext *context = redisConnectWithOptions(&options);
622
- ```
623
- 3. Call `redisSetPushCallback` with `NULL` once connected.
624
- ```c
625
- redisContext *context = redisConnect("127.0.0.1", 6379);
626
- redisSetPushCallback(context, NULL);
627
- ```
628
-
629
- _Note: With no handler configured, calls to `redisCommand` may generate more than one reply, so this strategy is only applicable when there's some kind of blocking`redisGetReply()` loop (e.g. `MONITOR` or `SUBSCRIBE` workloads)._
630
-
631
- ## Allocator injection
632
-
633
- Hiredis uses a pass-thru structure of function pointers defined in [alloc.h](https://github.com/redis/hiredis/blob/f5d25850/alloc.h#L41) that contain the currently configured allocation and deallocation functions. By default they just point to libc (`malloc`, `calloc`, `realloc`, etc).
634
-
635
- ### Overriding
636
-
637
- One can override the allocators like so:
638
-
639
- ```c
640
- hiredisAllocFuncs myfuncs = {
641
- .mallocFn = my_malloc,
642
- .callocFn = my_calloc,
643
- .reallocFn = my_realloc,
644
- .strdupFn = my_strdup,
645
- .freeFn = my_free,
646
- };
647
-
648
- // Override allocators (function returns current allocators if needed)
649
- hiredisAllocFuncs orig = hiredisSetAllocators(&myfuncs);
650
- ```
651
-
652
- To reset the allocators to their default libc function simply call:
653
-
654
- ```c
655
- hiredisResetAllocators();
656
- ```
657
-
658
- ## AUTHORS
659
-
660
- Salvatore Sanfilippo (antirez at gmail),\
661
- Pieter Noordhuis (pcnoordhuis at gmail)\
662
- Michael Grunder (michael dot grunder at gmail)
663
-
664
- _Hiredis is released under the BSD license._