summaryrefslogtreecommitdiff
path: root/async.c
diff options
context:
space:
mode:
authorMark Nunberg <mnunberg@haskalah.org>2017-11-27 15:49:28 -0500
committerMark Nunberg <mnunberg@haskalah.org>2019-02-20 09:10:10 -0500
commit08efa46599410e6b56ab19ed1c9a72c67476db9c (patch)
tree3d139ad26f4eeeec5ff43e8c9fe8866d6aa79a1e /async.c
parentba947bc93cc262c37db181f4684db1c37e803d6a (diff)
SSL for async I/O
Diffstat (limited to 'async.c')
-rw-r--r--async.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/async.c b/async.c
index 0cecd30..5a14d45 100644
--- a/async.c
+++ b/async.c
@@ -40,6 +40,7 @@
#include "net.h"
#include "dict.c"
#include "sds.h"
+#include "sslio.h"
#define _EL_ADD_READ(ctx) do { \
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
@@ -524,6 +525,87 @@ static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
}
}
+#ifndef HIREDIS_NOSSL
+/**
+ * Handle SSL when socket becomes available for reading. This also handles
+ * read-while-write and write-while-read
+ */
+static void asyncSslRead(redisAsyncContext *ac) {
+ int rv;
+ redisSsl *ssl = ac->c.ssl;
+ redisContext *c = &ac->c;
+
+ ssl->wantRead = 0;
+
+ if (ssl->pendingWrite) {
+ int done;
+
+ /* This is probably just a write event */
+ ssl->pendingWrite = 0;
+ rv = redisBufferWrite(c, &done);
+ if (rv == REDIS_ERR) {
+ __redisAsyncDisconnect(ac);
+ return;
+ } else if (!done) {
+ _EL_ADD_WRITE(ac);
+ }
+ }
+
+ rv = redisBufferRead(c);
+ if (rv == REDIS_ERR) {
+ __redisAsyncDisconnect(ac);
+ } else {
+ _EL_ADD_READ(ac);
+ redisProcessCallbacks(ac);
+ }
+}
+
+/**
+ * Handle SSL when socket becomes available for writing
+ */
+static void asyncSslWrite(redisAsyncContext *ac) {
+ int rv, done = 0;
+ redisSsl *ssl = ac->c.ssl;
+ redisContext *c = &ac->c;
+
+ ssl->pendingWrite = 0;
+ rv = redisBufferWrite(c, &done);
+ if (rv == REDIS_ERR) {
+ __redisAsyncDisconnect(ac);
+ return;
+ }
+
+ if (!done) {
+ if (ssl->wantRead) {
+ /* Need to read-before-write */
+ ssl->pendingWrite = 1;
+ _EL_DEL_WRITE(ac);
+ } else {
+ /* No extra reads needed, just need to write more */
+ _EL_ADD_WRITE(ac);
+ }
+ } else {
+ /* Already done! */
+ _EL_DEL_WRITE(ac);
+ }
+
+ /* Always reschedule a read */
+ _EL_ADD_READ(ac);
+}
+#else
+
+/* Just so we're able to compile */
+static void asyncSslRead(redisAsyncContext *ac) {
+ abort();
+ (void)ac;
+}
+static void asyncSslWrite(redisAsyncContext *ac) {
+ abort();
+ (void)ac;
+}
+
+#endif
+
/* This function should be called when the socket is readable.
* It processes all replies that can be read and executes their callbacks.
*/
@@ -539,6 +621,11 @@ void redisAsyncHandleRead(redisAsyncContext *ac) {
return;
}
+ if (c->flags & REDIS_SSL) {
+ asyncSslRead(ac);
+ return;
+ }
+
if (redisBufferRead(c) == REDIS_ERR) {
__redisAsyncDisconnect(ac);
} else {
@@ -561,6 +648,11 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
return;
}
+ if (c->flags & REDIS_SSL) {
+ asyncSslWrite(ac);
+ return;
+ }
+
if (redisBufferWrite(c,&done) == REDIS_ERR) {
__redisAsyncDisconnect(ac);
} else {