Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
297de989
Unverified
Commit
297de989
authored
Feb 21, 2019
by
Mark Nunberg
Committed by
GitHub
Feb 21, 2019
Browse files
Merge pull request #645 from redis/ssl
SSL Support
parents
4d00404b
ffceb87e
Changes
16
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
297de989
...
...
@@ -5,3 +5,4 @@
/*.dylib
/*.a
/*.pc
*.dSYM
.travis.yml
View file @
297de989
...
...
@@ -28,13 +28,14 @@ env:
-
BITS="64"
script
:
-
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
-
EXTRA_CMAKE_OPTS="-DENABLE_EXAMPLES:BOOL=ON -DHIREDIS_SSL:BOOL=ON";
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
if [ "$BITS" == "32" ]; then
CFLAGS="-m32 -Werror";
CXXFLAGS="-m32 -Werror";
LDFLAGS="-m32";
EXTRA_CMAKE_OPTS=;
else
EXTRA_CMAKE_OPTS="-DENABLE_EXAMPLES:BOOL=ON";
CFLAGS="-Werror";
CXXFLAGS="-Werror";
fi;
...
...
@@ -44,8 +45,8 @@ script:
CFLAGS="-m32 -Werror";
CXXFLAGS="-m32 -Werror";
LDFLAGS="-m32";
EXTRA_CMAKE_OPTS=;
else
EXTRA_CMAKE_OPTS="-DENABLE_EXAMPLES:BOOL=ON";
CFLAGS="-Werror";
CXXFLAGS="-Werror";
fi;
...
...
CMakeLists.txt
View file @
297de989
CMAKE_MINIMUM_REQUIRED
(
VERSION 3.0.0
)
INCLUDE
(
GNUInstallDirs
)
PROJECT
(
hiredis
)
OPTION
(
HIREDIS_SSL
"Link against OpenSSL"
OFF
)
MACRO
(
getVersionBit name
)
SET
(
VERSION_REGEX
"^#define
${
name
}
(.+)$"
)
...
...
@@ -27,7 +30,8 @@ ADD_LIBRARY(hiredis SHARED
hiredis.c
net.c
read.c
sds.c
)
sds.c
sslio.c
)
SET_TARGET_PROPERTIES
(
hiredis
PROPERTIES
...
...
@@ -44,9 +48,22 @@ INSTALL(FILES hiredis.h read.h sds.h async.h
INSTALL
(
FILES
${
CMAKE_CURRENT_BINARY_DIR
}
/hiredis.pc
DESTINATION
${
CMAKE_INSTALL_LIBDIR
}
/pkgconfig
)
IF
(
HIREDIS_SSL
)
IF
(
NOT OPENSSL_ROOT_DIR
)
IF
(
APPLE
)
SET
(
OPENSSL_ROOT_DIR
"/usr/local/opt/openssl"
)
ENDIF
()
ENDIF
()
FIND_PACKAGE
(
OpenSSL REQUIRED
)
ADD_DEFINITIONS
(
-DHIREDIS_SSL
)
INCLUDE_DIRECTORIES
(
"
${
OPENSSL_INCLUDE_DIR
}
"
)
TARGET_LINK_LIBRARIES
(
hiredis
${
OPENSSL_LIBRARIES
}
)
ENDIF
()
ENABLE_TESTING
()
ADD_EXECUTABLE
(
hiredis-test
test.c
)
ADD_EXECUTABLE
(
hiredis-test test.c
)
TARGET_LINK_LIBRARIES
(
hiredis-test hiredis
)
ADD_TEST
(
NAME hiredis-test
COMMAND
${
CMAKE_CURRENT_SOURCE_DIR
}
/test.sh
)
...
...
Makefile
View file @
297de989
...
...
@@ -3,8 +3,9 @@
# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>
# This file is released under the BSD license, see the COPYING file
OBJ
=
net.o hiredis.o sds.o async.o read.o
EXAMPLES
=
hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib
OBJ
=
net.o hiredis.o sds.o async.o read.o sslio.o
EXAMPLES
=
hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib
\
hiredis-example-ssl hiredis-example-libevent-ssl
TESTS
=
hiredis-test
LIBNAME
=
libhiredis
PKGCONFNAME
=
hiredis.pc
...
...
@@ -39,7 +40,7 @@ export REDIS_TEST_CONFIG
CC
:=
$(
shell
sh
-c
'type $${CC%% *
}
>/dev/null 2>/dev/null && echo
$(CC)
|| echo gcc'
)
CXX
:=
$(
shell
sh
-c
'type $${CXX%% *
}
>/dev/null 2>/dev/null && echo
$(CXX)
|| echo g++'
)
OPTIMIZATION
?=
-O3
WARNINGS
=
-Wall
-W
-Wstrict-prototypes
-Wwrite-strings
WARNINGS
=
-Wall
-W
-Wstrict-prototypes
-Wwrite-strings
-Wno-missing-field-initializers
DEBUG_FLAGS
?=
-g
-ggdb
REAL_CFLAGS
=
$(OPTIMIZATION)
-fPIC
$(CPPFLAGS)
$(CFLAGS)
$(WARNINGS)
$(DEBUG_FLAGS)
REAL_LDFLAGS
=
$(LDFLAGS)
...
...
@@ -49,12 +50,28 @@ STLIBSUFFIX=a
DYLIB_MINOR_NAME
=
$(LIBNAME)
.
$(DYLIBSUFFIX)
.
$(HIREDIS_SONAME)
DYLIB_MAJOR_NAME
=
$(LIBNAME)
.
$(DYLIBSUFFIX)
.
$(HIREDIS_MAJOR)
DYLIBNAME
=
$(LIBNAME)
.
$(DYLIBSUFFIX)
DYLIB_MAKE_CMD
=
$(CC)
-shared
-Wl
,-soname,
$(DYLIB_MINOR_NAME)
-o
$(DYLIBNAME)
$(LDFLAGS)
DYLIB_MAKE_CMD
=
$(CC)
-shared
-Wl
,-soname,
$(DYLIB_MINOR_NAME)
-o
$(DYLIBNAME)
STLIBNAME
=
$(LIBNAME)
.
$(STLIBSUFFIX)
STLIB_MAKE_CMD
=
$(AR)
rcs
$(STLIBNAME)
# Platform-specific overrides
uname_S
:=
$(
shell
sh
-c
'uname -s 2>/dev/null || echo not'
)
USE_SSL
?=
0
ifeq
($(USE_SSL),1)
# This is the prefix of openssl on my system. This should be the sane default
# based on the platform
ifeq
($(uname_S),Linux)
CFLAGS
+=
-DHIREDIS_SSL
LDFLAGS
+=
-lssl
-lcrypto
else
OPENSSL_PREFIX
?=
/usr/local/opt/openssl
CFLAGS
+=
-I
$(OPENSSL_PREFIX)
/include
-DHIREDIS_SSL
LDFLAGS
+=
-L
$(OPENSSL_PREFIX)
/lib
-lssl
-lcrypto
endif
endif
ifeq
($(uname_S),SunOS)
REAL_LDFLAGS
+=
-ldl
-lnsl
-lsocket
DYLIB_MAKE_CMD
=
$(CC)
-G
-o
$(DYLIBNAME)
-h
$(DYLIB_MINOR_NAME)
$(LDFLAGS)
...
...
@@ -70,14 +87,15 @@ all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME)
# Deps (use make dep to generate this)
async.o
:
async.c fmacros.h async.h hiredis.h read.h sds.h net.h dict.c dict.h
dict.o
:
dict.c fmacros.h dict.h
hiredis.o
:
hiredis.c fmacros.h hiredis.h read.h sds.h net.h
hiredis.o
:
hiredis.c fmacros.h hiredis.h read.h sds.h net.h
sslio.h
net.o
:
net.c fmacros.h net.h hiredis.h read.h sds.h
read.o
:
read.c fmacros.h read.h sds.h
sds.o
:
sds.c sds.h
sslio.o
:
sslio.c sslio.h hiredis.h
test.o
:
test.c fmacros.h hiredis.h read.h sds.h
$(DYLIBNAME)
:
$(OBJ)
$(DYLIB_MAKE_CMD)
$(OBJ)
$(DYLIB_MAKE_CMD)
$(OBJ)
$(REAL_LDFLAGS)
$(STLIBNAME)
:
$(OBJ)
$(STLIB_MAKE_CMD)
$(OBJ)
...
...
@@ -87,19 +105,25 @@ static: $(STLIBNAME)
# Binaries:
hiredis-example-libevent
:
examples/example-libevent.c adapters/libevent.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
-levent
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
-levent
$(STLIBNAME)
$(REAL_LDFLAGS)
hiredis-example-libevent-ssl
:
examples/example-libevent-ssl.c adapters/libevent.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
-levent
$(STLIBNAME)
$(REAL_LDFLAGS)
hiredis-example-libev
:
examples/example-libev.c adapters/libev.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
-lev
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
-lev
$(STLIBNAME)
$(REAL_LDFLAGS)
hiredis-example-glib
:
examples/example-glib.c adapters/glib.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
$(
shell
pkg-config
--cflags
--libs
glib-2.0
)
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
$(
shell
pkg-config
--cflags
--libs
glib-2.0
)
$(STLIBNAME)
$(REAL_LDFLAGS)
hiredis-example-ivykis
:
examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
-livykis
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
-livykis
$(STLIBNAME)
$(REAL_LDFLAGS)
hiredis-example-macosx
:
examples/example-macosx.c adapters/macosx.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
-framework
CoreFoundation
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
-framework
CoreFoundation
$(STLIBNAME)
$(REAL_LDFLAGS)
hiredis-example-ssl
:
examples/example-ssl.c $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
$(STLIBNAME)
$(REAL_LDFLAGS)
ifndef
AE_DIR
hiredis-example-ae
:
...
...
@@ -116,7 +140,7 @@ hiredis-example-libuv:
@
false
else
hiredis-example-libuv
:
examples/example-libuv.c adapters/libuv.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
-I
$(LIBUV_DIR)
/include
$<
$(LIBUV_DIR)
/.libs/libuv.a
-lpthread
-lrt
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
-I
$(LIBUV_DIR)
/include
$<
$(LIBUV_DIR)
/.libs/libuv.a
-lpthread
-lrt
$(STLIBNAME)
$(REAL_LDFLAGS)
endif
ifeq
($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),)
...
...
@@ -133,14 +157,14 @@ hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME)
endif
hiredis-example
:
examples/example.c $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
-I
.
$<
$(STLIBNAME)
$(REAL_LDFLAGS)
examples
:
$(EXAMPLES)
hiredis-test
:
test.o $(STLIBNAME)
hiredis-%
:
%.o $(STLIBNAME)
$(CC)
$(REAL_CFLAGS)
-o
$@
$
(REAL_LDFLAGS)
$<
$(STLIBNAME
)
$(CC)
$(REAL_CFLAGS)
-o
$@
$
<
$(STLIBNAME)
$(REAL_LDFLAGS
)
test
:
hiredis-test
./hiredis-test
...
...
@@ -158,7 +182,7 @@ clean:
rm
-rf
$(DYLIBNAME)
$(STLIBNAME)
$(TESTS)
$(PKGCONFNAME)
examples/hiredis-example
*
*
.o
*
.gcda
*
.gcno
*
.gcov
dep
:
$(CC)
-MM
*
.c
$(CC)
$(CPPFLAGS)
$(CFLAGS)
-MM
*
.c
INSTALL
?=
cp
-pPR
...
...
@@ -173,11 +197,14 @@ $(PKGCONFNAME): hiredis.h
@
echo
Description: Minimalistic C client library
for
Redis.
>>
$@
@
echo
Version:
$(HIREDIS_MAJOR)
.
$(HIREDIS_MINOR)
.
$(HIREDIS_PATCH)
>>
$@
@
echo
Libs:
-L
\$
${libdir}
-lhiredis
>>
$@
ifdef
USE_SSL
@
echo
Libs.private:
-lssl
-lcrypto
>>
$@
endif
@
echo
Cflags:
-I
\$
${includedir}
-D_FILE_OFFSET_BITS
=
64
>>
$@
install
:
$(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
mkdir
-p
$(INSTALL_INCLUDE_PATH)
$(INSTALL_INCLUDE_PATH)
/adapters
$(INSTALL_LIBRARY_PATH)
$(INSTALL)
hiredis.h async.h read.h sds.h
$(INSTALL_INCLUDE_PATH)
$(INSTALL)
hiredis.h async.h read.h sds.h
sslio.h
$(INSTALL_INCLUDE_PATH)
$(INSTALL)
adapters/
*
.h
$(INSTALL_INCLUDE_PATH)
/adapters
$(INSTALL)
$(DYLIBNAME)
$(INSTALL_LIBRARY_PATH)
/
$(DYLIB_MINOR_NAME)
cd
$(INSTALL_LIBRARY_PATH)
&&
ln
-sf
$(DYLIB_MINOR_NAME)
$(DYLIBNAME)
...
...
adapters/libevent.h
View file @
297de989
...
...
@@ -34,48 +34,113 @@
#include "../hiredis.h"
#include "../async.h"
#define REDIS_LIBEVENT_DELETED 0x01
#define REDIS_LIBEVENT_ENTERED 0x02
typedef
struct
redisLibeventEvents
{
redisAsyncContext
*
context
;
struct
event
*
rev
,
*
wev
;
struct
event
*
ev
;
struct
event_base
*
base
;
struct
timeval
tv
;
short
flags
;
short
state
;
}
redisLibeventEvents
;
static
void
redisLibeventReadEvent
(
int
fd
,
short
event
,
void
*
arg
)
{
((
void
)
fd
);
((
void
)
event
);
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
arg
;
redisAsyncHandleRead
(
e
->
context
);
static
void
redisLibeventDestroy
(
redisLibeventEvents
*
e
)
{
free
(
e
);
}
static
void
redisLibevent
WriteEvent
(
int
fd
,
short
event
,
void
*
arg
)
{
((
void
)
fd
);
((
void
)
event
);
static
void
redisLibevent
Handler
(
int
fd
,
short
event
,
void
*
arg
)
{
((
void
)
fd
);
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
arg
;
redisAsyncHandleWrite
(
e
->
context
);
e
->
state
|=
REDIS_LIBEVENT_ENTERED
;
#define CHECK_DELETED() if (e->state & REDIS_LIBEVENT_DELETED) {\
redisLibeventDestroy(e);\
return; \
}
if
((
event
&
EV_TIMEOUT
)
&&
(
e
->
state
&
REDIS_LIBEVENT_DELETED
)
==
0
)
{
redisAsyncHandleTimeout
(
e
->
context
);
CHECK_DELETED
();
}
if
((
event
&
EV_READ
)
&&
e
->
context
&&
(
e
->
state
&
REDIS_LIBEVENT_DELETED
)
==
0
)
{
redisAsyncHandleRead
(
e
->
context
);
CHECK_DELETED
();
}
if
((
event
&
EV_WRITE
)
&&
e
->
context
&&
(
e
->
state
&
REDIS_LIBEVENT_DELETED
)
==
0
)
{
redisAsyncHandleWrite
(
e
->
context
);
CHECK_DELETED
();
}
e
->
state
&=
~
REDIS_LIBEVENT_ENTERED
;
#undef CHECK_DELETED
}
static
void
redisLibeventUpdate
(
void
*
privdata
,
short
flag
,
int
isRemove
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
const
struct
timeval
*
tv
=
e
->
tv
.
tv_sec
||
e
->
tv
.
tv_usec
?
&
e
->
tv
:
NULL
;
if
(
isRemove
)
{
if
((
e
->
flags
&
flag
)
==
0
)
{
return
;
}
else
{
e
->
flags
&=
~
flag
;
}
}
else
{
if
(
e
->
flags
&
flag
)
{
return
;
}
else
{
e
->
flags
|=
flag
;
}
}
event_del
(
e
->
ev
);
event_assign
(
e
->
ev
,
e
->
base
,
e
->
context
->
c
.
fd
,
e
->
flags
|
EV_PERSIST
,
redisLibeventHandler
,
privdata
);
event_add
(
e
->
ev
,
tv
);
}
static
void
redisLibeventAddRead
(
void
*
privdata
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
event_add
(
e
->
rev
,
NULL
);
redisLibeventUpdate
(
privdata
,
EV_READ
,
0
);
}
static
void
redisLibeventDelRead
(
void
*
privdata
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
event_del
(
e
->
rev
);
redisLibeventUpdate
(
privdata
,
EV_READ
,
1
);
}
static
void
redisLibeventAddWrite
(
void
*
privdata
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
event_add
(
e
->
wev
,
NULL
);
redisLibeventUpdate
(
privdata
,
EV_WRITE
,
0
);
}
static
void
redisLibeventDelWrite
(
void
*
privdata
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
event_del
(
e
->
wev
);
redisLibeventUpdate
(
privdata
,
EV_WRITE
,
1
);
}
static
void
redisLibeventCleanup
(
void
*
privdata
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
event_free
(
e
->
rev
);
event_free
(
e
->
wev
);
free
(
e
);
if
(
!
e
)
{
return
;
}
event_del
(
e
->
ev
);
event_free
(
e
->
ev
);
e
->
ev
=
NULL
;
if
(
e
->
state
&
REDIS_LIBEVENT_ENTERED
)
{
e
->
state
|=
REDIS_LIBEVENT_DELETED
;
}
else
{
redisLibeventDestroy
(
e
);
}
}
static
void
redisLibeventSetTimeout
(
void
*
privdata
,
struct
timeval
tv
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
short
flags
=
e
->
flags
;
e
->
flags
=
0
;
e
->
tv
=
tv
;
redisLibeventUpdate
(
e
,
flags
,
0
);
}
static
int
redisLibeventAttach
(
redisAsyncContext
*
ac
,
struct
event_base
*
base
)
{
...
...
@@ -87,7 +152,7 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
return
REDIS_ERR
;
/* Create container for context and r/w events */
e
=
(
redisLibeventEvents
*
)
m
alloc
(
sizeof
(
*
e
));
e
=
(
redisLibeventEvents
*
)
c
alloc
(
1
,
sizeof
(
*
e
));
e
->
context
=
ac
;
/* Register functions to start/stop listening for events */
...
...
@@ -96,13 +161,12 @@ static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
ac
->
ev
.
addWrite
=
redisLibeventAddWrite
;
ac
->
ev
.
delWrite
=
redisLibeventDelWrite
;
ac
->
ev
.
cleanup
=
redisLibeventCleanup
;
ac
->
ev
.
scheduleTimer
=
redisLibeventSetTimeout
;
ac
->
ev
.
data
=
e
;
/* Initialize and install read/write events */
e
->
rev
=
event_new
(
base
,
c
->
fd
,
EV_READ
,
redisLibeventReadEvent
,
e
);
e
->
wev
=
event_new
(
base
,
c
->
fd
,
EV_WRITE
,
redisLibeventWriteEvent
,
e
);
event_add
(
e
->
rev
,
NULL
);
event_add
(
e
->
wev
,
NULL
);
e
->
ev
=
event_new
(
base
,
c
->
fd
,
EV_READ
|
EV_WRITE
,
redisLibeventHandler
,
e
);
e
->
base
=
base
;
return
REDIS_OK
;
}
#endif
async.c
View file @
297de989
...
...
@@ -40,16 +40,21 @@
#include "net.h"
#include "dict.c"
#include "sds.h"
#include "sslio.h"
#define _EL_ADD_READ(ctx) do { \
#define _EL_ADD_READ(ctx) \
do { \
refreshTimeout(ctx); \
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
} while(0)
} while
(0)
#define _EL_DEL_READ(ctx) do { \
if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
} while(0)
#define _EL_ADD_WRITE(ctx) do { \
#define _EL_ADD_WRITE(ctx) \
do { \
refreshTimeout(ctx); \
if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \
} while(0)
} while
(0)
#define _EL_DEL_WRITE(ctx) do { \
if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \
} while(0)
...
...
@@ -57,6 +62,19 @@
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
} while(0);
static
void
refreshTimeout
(
redisAsyncContext
*
ctx
)
{
if
(
ctx
->
c
.
timeout
&&
ctx
->
ev
.
scheduleTimer
&&
(
ctx
->
c
.
timeout
->
tv_sec
||
ctx
->
c
.
timeout
->
tv_usec
))
{
ctx
->
ev
.
scheduleTimer
(
ctx
->
ev
.
data
,
*
ctx
->
c
.
timeout
);
// } else {
// printf("Not scheduling timer.. (tmo=%p)\n", ctx->c.timeout);
// if (ctx->c.timeout){
// printf("tv_sec: %u. tv_usec: %u\n", ctx->c.timeout->tv_sec,
// ctx->c.timeout->tv_usec);
// }
}
}
/* Forward declaration of function in hiredis.c */
int
__redisAppendCommand
(
redisContext
*
c
,
const
char
*
cmd
,
size_t
len
);
...
...
@@ -126,6 +144,7 @@ static redisAsyncContext *redisAsyncInitialize(redisContext *c) {
ac
->
ev
.
addWrite
=
NULL
;
ac
->
ev
.
delWrite
=
NULL
;
ac
->
ev
.
cleanup
=
NULL
;
ac
->
ev
.
scheduleTimer
=
NULL
;
ac
->
onConnect
=
NULL
;
ac
->
onDisconnect
=
NULL
;
...
...
@@ -150,56 +169,52 @@ static void __redisAsyncCopyError(redisAsyncContext *ac) {
ac
->
errstr
=
c
->
errstr
;
}
redisAsyncContext
*
redisAsyncConnect
(
const
char
*
ip
,
int
port
)
{
redisAsyncContext
*
redisAsyncConnectWithOptions
(
const
redisOptions
*
options
)
{
redisOptions
myOptions
=
*
options
;
redisContext
*
c
;
redisAsyncContext
*
ac
;
c
=
redisConnectNonBlock
(
ip
,
port
);
if
(
c
==
NULL
)
myOptions
.
options
|=
REDIS_OPT_NONBLOCK
;
c
=
redisConnectWithOptions
(
&
myOptions
);
if
(
c
==
NULL
)
{
return
NULL
;
}
ac
=
redisAsyncInitialize
(
c
);
if
(
ac
==
NULL
)
{
redisFree
(
c
);
return
NULL
;
}
__redisAsyncCopyError
(
ac
);
return
ac
;
}
redisAsyncContext
*
redisAsyncConnect
(
const
char
*
ip
,
int
port
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
return
redisAsyncConnectWithOptions
(
&
options
);
}
redisAsyncContext
*
redisAsyncConnectBind
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redis
Context
*
c
=
redisConnectBindNonBlock
(
ip
,
port
,
source_addr
)
;
redisAsyncContext
*
ac
=
redisAsyncInitialize
(
c
);
__redisAsyncCopyError
(
ac
)
;
return
ac
;
redis
Options
options
=
{
0
}
;
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
endpoint
.
tcp
.
source_addr
=
source_addr
;
return
redisAsyncConnectWithOptions
(
&
options
)
;
}
redisAsyncContext
*
redisAsyncConnectBindWithReuse
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisContext
*
c
=
redisConnectBindNonBlockWithReuse
(
ip
,
port
,
source_addr
);
redisAsyncContext
*
ac
=
redisAsyncInitialize
(
c
);
__redisAsyncCopyError
(
ac
);
return
ac
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
options
|=
REDIS_OPT_REUSEADDR
;
options
.
endpoint
.
tcp
.
source_addr
=
source_addr
;
return
redisAsyncConnectWithOptions
(
&
options
);
}
redisAsyncContext
*
redisAsyncConnectUnix
(
const
char
*
path
)
{
redisContext
*
c
;
redisAsyncContext
*
ac
;
c
=
redisConnectUnixNonBlock
(
path
);
if
(
c
==
NULL
)
return
NULL
;
ac
=
redisAsyncInitialize
(
c
);
if
(
ac
==
NULL
)
{
redisFree
(
c
);
return
NULL
;
}
__redisAsyncCopyError
(
ac
);
return
ac
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
return
redisAsyncConnectWithOptions
(
&
options
);
}
int
redisAsyncSetConnectCallback
(
redisAsyncContext
*
ac
,
redisConnectCallback
*
fn
)
{
...
...
@@ -346,7 +361,9 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
/* For non-clean disconnects, __redisAsyncFree() will execute pending
* callbacks with a NULL-reply. */
__redisAsyncFree
(
ac
);
if
(
!
(
c
->
flags
&
REDIS_NO_AUTO_FREE
))
{
__redisAsyncFree
(
ac
);
}
}
/* Tries to do a clean disconnect from Redis, meaning it stops new commands
...
...
@@ -358,6 +375,9 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
void
redisAsyncDisconnect
(
redisAsyncContext
*
ac
)
{
redisContext
*
c
=
&
(
ac
->
c
);
c
->
flags
|=
REDIS_DISCONNECTING
;
/** unset the auto-free flag here, because disconnect undoes this */
c
->
flags
&=
~
REDIS_NO_AUTO_FREE
;
if
(
!
(
c
->
flags
&
REDIS_IN_CALLBACK
)
&&
ac
->
replies
.
head
==
NULL
)
__redisAsyncDisconnect
(
ac
);
}
...
...
@@ -524,6 +544,76 @@ static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
}
}
/**
* Handle SSL when socket becomes available for reading. This also handles
* read-while-write and write-while-read.
*
* These functions will not work properly unless `HIREDIS_SSL` is defined
* (however, they will compile)
*/
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
);
}
/* This function should be called when the socket is readable.
* It processes all replies that can be read and executes their callbacks.
*/
...
...
@@ -539,6 +629,11 @@ void redisAsyncHandleRead(redisAsyncContext *ac) {
return
;
}
if
(
c
->
flags
&
REDIS_SSL
)
{
asyncSslRead
(
ac
);
return
;
}
if
(
redisBufferRead
(
c
)
==
REDIS_ERR
)
{
__redisAsyncDisconnect
(
ac
);
}
else
{
...
...
@@ -561,6 +656,11 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
return
;
}
if
(
c
->
flags
&
REDIS_SSL
)
{
asyncSslWrite
(
ac
);
return
;
}
if
(
redisBufferWrite
(
c
,
&
done
)
==
REDIS_ERR
)
{
__redisAsyncDisconnect
(
ac
);
}
else
{
...
...
@@ -575,6 +675,30 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
}
}
void
__redisSetError
(
redisContext
*
c
,
int
type
,
const
char
*
str
);
void
redisAsyncHandleTimeout
(
redisAsyncContext
*
ac
)
{
redisContext
*
c
=
&
(
ac
->
c
);
redisCallback
cb
;
if
((
c
->
flags
&
REDIS_CONNECTED
)
&&
ac
->
replies
.
head
==
NULL
)
{
/* Nothing to do - just an idle timeout */
return
;
}
if
(
!
c
->
err
)
{
__redisSetError
(
c
,
REDIS_ERR_TIMEOUT
,
"Timeout"
);
}
if
(
!
(
c
->
flags
&
REDIS_CONNECTED
)
&&
ac
->
onConnect
)
{
ac
->
onConnect
(
ac
,
REDIS_ERR
);
}
while
(
__redisShiftCallback
(
&
ac
->
replies
,
&
cb
)
==
REDIS_OK
)
{
__redisRunCallback
(
ac
,
&
cb
,
NULL
);
}
}
/* Sets a pointer to the first argument and its length starting at p. Returns
* the number of bytes to skip to get to the following argument. */
static
const
char
*
nextArgument
(
const
char
*
start
,
const
char
**
str
,
size_t
*
len
)
{
...
...
@@ -714,3 +838,16 @@ int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
int
status
=
__redisAsyncCommand
(
ac
,
fn
,
privdata
,
cmd
,
len
);
return
status
;
}
void
redisAsyncSetTimeout
(
redisAsyncContext
*
ac
,
struct
timeval
tv
)
{
if
(
!
ac
->
c
.
timeout
)
{
ac
->
c
.
timeout
=
calloc
(
1
,
sizeof
(
tv
));
}
if
(
tv
.
tv_sec
==
ac
->
c
.
timeout
->
tv_sec
&&
tv
.
tv_usec
==
ac
->
c
.
timeout
->
tv_usec
)
{
return
;
}
*
ac
->
c
.
timeout
=
tv
;
}
async.h
View file @
297de989
...
...
@@ -57,6 +57,7 @@ typedef struct redisCallbackList {
/* Connection callback prototypes */
typedef
void
(
redisDisconnectCallback
)(
const
struct
redisAsyncContext
*
,
int
status
);
typedef
void
(
redisConnectCallback
)(
const
struct
redisAsyncContext
*
,
int
status
);
typedef
void
(
redisTimerCallback
)(
void
*
timer
,
void
*
privdata
);
/* Context for an async connection to Redis */
typedef
struct
redisAsyncContext
{
...
...
@@ -81,6 +82,7 @@ typedef struct redisAsyncContext {
void
(
*
addWrite
)(
void
*
privdata
);
void
(
*
delWrite
)(
void
*
privdata
);
void
(
*
cleanup
)(
void
*
privdata
);
void
(
*
scheduleTimer
)(
void
*
privdata
,
struct
timeval
tv
);
}
ev
;
/* Called when either the connection is terminated due to an error or per
...
...
@@ -106,6 +108,7 @@ typedef struct redisAsyncContext {
}
redisAsyncContext
;
/* Functions that proxy to hiredis */
redisAsyncContext
*
redisAsyncConnectWithOptions
(
const
redisOptions
*
options
);
redisAsyncContext
*
redisAsyncConnect
(
const
char
*
ip
,
int
port
);
redisAsyncContext
*
redisAsyncConnectBind
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
);
redisAsyncContext
*
redisAsyncConnectBindWithReuse
(
const
char
*
ip
,
int
port
,
...
...
@@ -113,12 +116,15 @@ redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
redisAsyncContext
*
redisAsyncConnectUnix
(
const
char
*
path
);
int
redisAsyncSetConnectCallback
(
redisAsyncContext
*
ac
,
redisConnectCallback
*
fn
);
int
redisAsyncSetDisconnectCallback
(
redisAsyncContext
*
ac
,
redisDisconnectCallback
*
fn
);
void
redisAsyncSetTimeout
(
redisAsyncContext
*
ac
,
struct
timeval
tv
);
void
redisAsyncDisconnect
(
redisAsyncContext
*
ac
);
void
redisAsyncFree
(
redisAsyncContext
*
ac
);
/* Handle read/write events */
void
redisAsyncHandleRead
(
redisAsyncContext
*
ac
);
void
redisAsyncHandleWrite
(
redisAsyncContext
*
ac
);
void
redisAsyncHandleTimeout
(
redisAsyncContext
*
ac
);
/* Command functions for an async context. Write the command to the
* output buffer and register the provided callback. */
...
...
examples/example-libevent-ssl.c
0 → 100644
View file @
297de989
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <hiredis.h>
#include <async.h>
#include <adapters/libevent.h>
void
getCallback
(
redisAsyncContext
*
c
,
void
*
r
,
void
*
privdata
)
{
redisReply
*
reply
=
r
;
if
(
reply
==
NULL
)
return
;
printf
(
"argv[%s]: %s
\n
"
,
(
char
*
)
privdata
,
reply
->
str
);
/* Disconnect after receiving the reply to GET */
redisAsyncDisconnect
(
c
);
}
void
connectCallback
(
const
redisAsyncContext
*
c
,
int
status
)
{
if
(
status
!=
REDIS_OK
)
{
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
;
}
printf
(
"Connected...
\n
"
);
}
void
disconnectCallback
(
const
redisAsyncContext
*
c
,
int
status
)
{
if
(
status
!=
REDIS_OK
)
{
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
;
}
printf
(
"Disconnected...
\n
"
);
}
int
main
(
int
argc
,
char
**
argv
)
{
signal
(
SIGPIPE
,
SIG_IGN
);
struct
event_base
*
base
=
event_base_new
();
if
(
argc
<
5
)
{
fprintf
(
stderr
,
"Usage: %s <key> <host> <port> <cert> <certKey> [ca]
\n
"
,
argv
[
0
]);
exit
(
1
);
}
const
char
*
value
=
argv
[
1
];
size_t
nvalue
=
strlen
(
value
);
const
char
*
hostname
=
argv
[
2
];
int
port
=
atoi
(
argv
[
3
]);
const
char
*
cert
=
argv
[
4
];
const
char
*
certKey
=
argv
[
5
];
const
char
*
caCert
=
argc
>
5
?
argv
[
6
]
:
NULL
;
redisAsyncContext
*
c
=
redisAsyncConnect
(
hostname
,
port
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
1
;
}
if
(
redisSecureConnection
(
&
c
->
c
,
caCert
,
cert
,
certKey
,
"sni"
)
!=
REDIS_OK
)
{
printf
(
"SSL Error!
\n
"
);
exit
(
1
);
}
redisLibeventAttach
(
c
,
base
);
redisAsyncSetConnectCallback
(
c
,
connectCallback
);
redisAsyncSetDisconnectCallback
(
c
,
disconnectCallback
);
redisAsyncCommand
(
c
,
NULL
,
NULL
,
"SET key %b"
,
value
,
nvalue
);
redisAsyncCommand
(
c
,
getCallback
,
(
char
*
)
"end-1"
,
"GET key"
);
event_base_dispatch
(
base
);
return
0
;
}
examples/example-libevent.c
View file @
297de989
...
...
@@ -9,7 +9,12 @@
void
getCallback
(
redisAsyncContext
*
c
,
void
*
r
,
void
*
privdata
)
{
redisReply
*
reply
=
r
;
if
(
reply
==
NULL
)
return
;
if
(
reply
==
NULL
)
{
if
(
c
->
errstr
)
{
printf
(
"errstr: %s
\n
"
,
c
->
errstr
);
}
return
;
}
printf
(
"argv[%s]: %s
\n
"
,
(
char
*
)
privdata
,
reply
->
str
);
/* Disconnect after receiving the reply to GET */
...
...
@@ -35,8 +40,14 @@ void disconnectCallback(const redisAsyncContext *c, int status) {
int
main
(
int
argc
,
char
**
argv
)
{
signal
(
SIGPIPE
,
SIG_IGN
);
struct
event_base
*
base
=
event_base_new
();
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
"127.0.0.1"
,
6379
);
struct
timeval
tv
=
{
0
};
tv
.
tv_sec
=
1
;
options
.
timeout
=
&
tv
;
redisAsyncContext
*
c
=
redisAsyncConnect
(
"127.0.0.1"
,
6379
);
redisAsyncContext
*
c
=
redisAsyncConnect
WithOptions
(
&
options
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
...
...
examples/example-ssl.c
0 → 100644
View file @
297de989
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis.h>
int
main
(
int
argc
,
char
**
argv
)
{
unsigned
int
j
;
redisContext
*
c
;
redisReply
*
reply
;
if
(
argc
<
4
)
{
printf
(
"Usage: %s <host> <port> <cert> <key> [ca]
\n
"
,
argv
[
0
]);
exit
(
1
);
}
const
char
*
hostname
=
(
argc
>
1
)
?
argv
[
1
]
:
"127.0.0.1"
;
int
port
=
atoi
(
argv
[
2
]);
const
char
*
cert
=
argv
[
3
];
const
char
*
key
=
argv
[
4
];
const
char
*
ca
=
argc
>
4
?
argv
[
5
]
:
NULL
;
struct
timeval
timeout
=
{
1
,
500000
};
// 1.5 seconds
c
=
redisConnectWithTimeout
(
hostname
,
port
,
timeout
);
if
(
c
==
NULL
||
c
->
err
)
{
if
(
c
)
{
printf
(
"Connection error: %s
\n
"
,
c
->
errstr
);
redisFree
(
c
);
}
else
{
printf
(
"Connection error: can't allocate redis context
\n
"
);
}
exit
(
1
);
}
if
(
redisSecureConnection
(
c
,
ca
,
cert
,
key
,
"sni"
)
!=
REDIS_OK
)
{
printf
(
"Couldn't initialize SSL!
\n
"
);
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
redisFree
(
c
);
exit
(
1
);
}
/* PING server */
reply
=
redisCommand
(
c
,
"PING"
);
printf
(
"PING: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Set a key */
reply
=
redisCommand
(
c
,
"SET %s %s"
,
"foo"
,
"hello world"
);
printf
(
"SET: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Set a key using binary safe API */
reply
=
redisCommand
(
c
,
"SET %b %b"
,
"bar"
,
(
size_t
)
3
,
"hello"
,
(
size_t
)
5
);
printf
(
"SET (binary API): %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Try a GET and two INCR */
reply
=
redisCommand
(
c
,
"GET foo"
);
printf
(
"GET foo: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
reply
=
redisCommand
(
c
,
"INCR counter"
);
printf
(
"INCR counter: %lld
\n
"
,
reply
->
integer
);
freeReplyObject
(
reply
);
/* again ... */
reply
=
redisCommand
(
c
,
"INCR counter"
);
printf
(
"INCR counter: %lld
\n
"
,
reply
->
integer
);
freeReplyObject
(
reply
);
/* Create a list of numbers, from 0 to 9 */
reply
=
redisCommand
(
c
,
"DEL mylist"
);
freeReplyObject
(
reply
);
for
(
j
=
0
;
j
<
10
;
j
++
)
{
char
buf
[
64
];
snprintf
(
buf
,
64
,
"%u"
,
j
);
reply
=
redisCommand
(
c
,
"LPUSH mylist element-%s"
,
buf
);
freeReplyObject
(
reply
);
}
/* Let's check what we have inside the list */
reply
=
redisCommand
(
c
,
"LRANGE mylist 0 -1"
);
if
(
reply
->
type
==
REDIS_REPLY_ARRAY
)
{
for
(
j
=
0
;
j
<
reply
->
elements
;
j
++
)
{
printf
(
"%u) %s
\n
"
,
j
,
reply
->
element
[
j
]
->
str
);
}
}
freeReplyObject
(
reply
);
/* Disconnects and frees the context */
redisFree
(
c
);
return
0
;
}
hiredis.c
View file @
297de989
...
...
@@ -42,6 +42,7 @@
#include "hiredis.h"
#include "net.h"
#include "sds.h"
#include "sslio.h"
static
redisReply
*
createReplyObject
(
int
type
);
static
void
*
createStringObject
(
const
redisReadTask
*
task
,
char
*
str
,
size_t
len
);
...
...
@@ -583,10 +584,10 @@ redisReader *redisReaderCreate(void) {
return
redisReaderCreateWithFunctions
(
&
defaultFunctions
);
}
static
redisContext
*
redisContextInit
(
void
)
{
static
redisContext
*
redisContextInit
(
const
redisOptions
*
options
)
{
redisContext
*
c
;
c
=
calloc
(
1
,
sizeof
(
redisContext
));
c
=
calloc
(
1
,
sizeof
(
*
c
));
if
(
c
==
NULL
)
return
NULL
;
...
...
@@ -597,7 +598,7 @@ static redisContext *redisContextInit(void) {
redisFree
(
c
);
return
NULL
;
}
(
void
)
options
;
/* options are used in other functions */
return
c
;
}
...
...
@@ -614,6 +615,10 @@ void redisFree(redisContext *c) {
free
(
c
->
unix_sock
.
path
);
free
(
c
->
timeout
);
free
(
c
->
saddr
);
if
(
c
->
ssl
)
{
redisFreeSsl
(
c
->
ssl
);
}
memset
(
c
,
0xff
,
sizeof
(
*
c
));
free
(
c
);
}
...
...
@@ -652,112 +657,109 @@ int redisReconnect(redisContext *c) {
return
REDIS_ERR
;
}
redisContext
*
redisConnectWithOptions
(
const
redisOptions
*
options
)
{
redisContext
*
c
=
redisContextInit
(
options
);
if
(
c
==
NULL
)
{
return
NULL
;
}
if
(
!
(
options
->
options
&
REDIS_OPT_NONBLOCK
))
{
c
->
flags
|=
REDIS_BLOCK
;
}
if
(
options
->
options
&
REDIS_OPT_REUSEADDR
)
{
c
->
flags
|=
REDIS_REUSEADDR
;
}
if
(
options
->
options
&
REDIS_OPT_NOAUTOFREE
)
{
c
->
flags
|=
REDIS_NO_AUTO_FREE
;
}
if
(
options
->
type
==
REDIS_CONN_TCP
)
{
redisContextConnectBindTcp
(
c
,
options
->
endpoint
.
tcp
.
ip
,
options
->
endpoint
.
tcp
.
port
,
options
->
timeout
,
options
->
endpoint
.
tcp
.
source_addr
);
}
else
if
(
options
->
type
==
REDIS_CONN_UNIX
)
{
redisContextConnectUnix
(
c
,
options
->
endpoint
.
unix_socket
,
options
->
timeout
);
}
else
if
(
options
->
type
==
REDIS_CONN_USERFD
)
{
c
->
fd
=
options
->
endpoint
.
fd
;
c
->
flags
|=
REDIS_CONNECTED
;
}
else
{
// Unknown type - FIXME - FREE
return
NULL
;
}
return
c
;
}
/* Connect to a Redis instance. On error the field error in the returned
* context will be set to the return value of the error function.
* When no set of reply functions is given, the default set will be used. */
redisContext
*
redisConnect
(
const
char
*
ip
,
int
port
)
{
redisContext
*
c
;
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
|=
REDIS_BLOCK
;
redisContextConnectTcp
(
c
,
ip
,
port
,
NULL
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectWithTimeout
(
const
char
*
ip
,
int
port
,
const
struct
timeval
tv
)
{
redisContext
*
c
;
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
|=
REDIS_BLOCK
;
redisContextConnectTcp
(
c
,
ip
,
port
,
&
tv
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
timeout
=
&
tv
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectNonBlock
(
const
char
*
ip
,
int
port
)
{
redisContext
*
c
;
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
&=
~
REDIS_BLOCK
;
redisContextConnectTcp
(
c
,
ip
,
port
,
NULL
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
options
|=
REDIS_OPT_NONBLOCK
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectBindNonBlock
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisContext
*
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
&=
~
REDIS_BLOCK
;
redisContextConnectBindTcp
(
c
,
ip
,
port
,
NULL
,
source_addr
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
endpoint
.
tcp
.
source_addr
=
source_addr
;
options
.
options
|=
REDIS_OPT_NONBLOCK
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectBindNonBlockWithReuse
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisContext
*
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
&=
~
REDIS_BLOCK
;
c
->
flags
|=
REDIS_REUSEADDR
;
redisContextConnectBindTcp
(
c
,
ip
,
port
,
NULL
,
source_addr
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
endpoint
.
tcp
.
source_addr
=
source_addr
;
options
.
options
|=
REDIS_OPT_NONBLOCK
|
REDIS_OPT_REUSEADDR
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectUnix
(
const
char
*
path
)
{
redisContext
*
c
;
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
|=
REDIS_BLOCK
;
redisContextConnectUnix
(
c
,
path
,
NULL
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectUnixWithTimeout
(
const
char
*
path
,
const
struct
timeval
tv
)
{
redisContext
*
c
;
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
|=
REDIS_BLOCK
;
redisContextConnectUnix
(
c
,
path
,
&
tv
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
options
.
timeout
=
&
tv
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectUnixNonBlock
(
const
char
*
path
)
{
redisContext
*
c
;
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
&=
~
REDIS_BLOCK
;
redisContextConnectUnix
(
c
,
path
,
NULL
);
return
c
;
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
options
.
options
|=
REDIS_OPT_NONBLOCK
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectFd
(
int
fd
)
{
redis
Context
*
c
;
c
=
redisContextInit
()
;
if
(
c
==
NULL
)
return
NULL
;
redis
Options
options
=
{
0
}
;
options
.
type
=
REDIS_CONN_USERFD
;
options
.
endpoint
.
fd
=
fd
;
return
redisConnectWithOptions
(
&
options
);
}
c
->
fd
=
fd
;
c
->
flags
|=
REDIS_BLOCK
|
REDIS_CONNECTED
;
return
c
;
int
redisSecureConnection
(
redisContext
*
c
,
const
char
*
caPath
,
const
char
*
certPath
,
const
char
*
keyPath
,
const
char
*
servername
)
{
return
redisSslCreate
(
c
,
caPath
,
certPath
,
keyPath
,
servername
)
;
}
/* Set read/write timeout on a blocking socket. */
...
...
@@ -774,6 +776,24 @@ int redisEnableKeepAlive(redisContext *c) {
return
REDIS_OK
;
}
static
int
rawRead
(
redisContext
*
c
,
char
*
buf
,
size_t
bufcap
)
{
int
nread
=
read
(
c
->
fd
,
buf
,
bufcap
);
if
(
nread
==
-
1
)
{
if
((
errno
==
EAGAIN
&&
!
(
c
->
flags
&
REDIS_BLOCK
))
||
(
errno
==
EINTR
))
{
/* Try again later */
return
0
;
}
else
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
NULL
);
return
-
1
;
}
}
else
if
(
nread
==
0
)
{
__redisSetError
(
c
,
REDIS_ERR_EOF
,
"Server closed the connection"
);
return
-
1
;
}
else
{
return
nread
;
}
}
/* Use this function to handle a read event on the descriptor. It will try
* and read some bytes from the socket and feed them to the reply parser.
*
...
...
@@ -787,26 +807,33 @@ int redisBufferRead(redisContext *c) {
if
(
c
->
err
)
return
REDIS_ERR
;
nread
=
read
(
c
->
fd
,
buf
,
sizeof
(
buf
));
if
(
nread
==
-
1
)
{
if
((
errno
==
EAGAIN
&&
!
(
c
->
flags
&
REDIS_BLOCK
))
||
(
errno
==
EINTR
))
{
/* Try again later */
}
else
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
NULL
);
nread
=
c
->
flags
&
REDIS_SSL
?
redisSslRead
(
c
,
buf
,
sizeof
(
buf
))
:
rawRead
(
c
,
buf
,
sizeof
(
buf
));
if
(
nread
>
0
)
{
if
(
redisReaderFeed
(
c
->
reader
,
buf
,
nread
)
!=
REDIS_OK
)
{
__redisSetError
(
c
,
c
->
reader
->
err
,
c
->
reader
->
errstr
);
return
REDIS_ERR
;
}
else
{
}
}
else
if
(
nread
==
0
)
{
__redisSetError
(
c
,
REDIS_ERR_EOF
,
"Server closed the connection"
);
}
else
if
(
nread
<
0
)
{
return
REDIS_ERR
;
}
else
{
if
(
redisReaderFeed
(
c
->
reader
,
buf
,
nread
)
!=
REDIS_OK
)
{
__redisSetError
(
c
,
c
->
reader
->
err
,
c
->
reader
->
errstr
);
return
REDIS_ERR
;
}
}
return
REDIS_OK
;
}
static
int
rawWrite
(
redisContext
*
c
)
{
int
nwritten
=
write
(
c
->
fd
,
c
->
obuf
,
sdslen
(
c
->
obuf
));
if
(
nwritten
<
0
)
{
if
((
errno
==
EAGAIN
&&
!
(
c
->
flags
&
REDIS_BLOCK
))
||
(
errno
==
EINTR
))
{
/* Try again later */
}
else
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
NULL
);
return
-
1
;
}
}
return
nwritten
;
}
/* Write the output buffer to the socket.
*
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
...
...
@@ -817,21 +844,15 @@ int redisBufferRead(redisContext *c) {
* c->errstr to hold the appropriate error string.
*/
int
redisBufferWrite
(
redisContext
*
c
,
int
*
done
)
{
int
nwritten
;
/* Return early when the context has seen an error. */
if
(
c
->
err
)
return
REDIS_ERR
;
if
(
sdslen
(
c
->
obuf
)
>
0
)
{
nwritten
=
write
(
c
->
fd
,
c
->
obuf
,
sdslen
(
c
->
obuf
));
if
(
nwritten
==
-
1
)
{
if
((
errno
==
EAGAIN
&&
!
(
c
->
flags
&
REDIS_BLOCK
))
||
(
errno
==
EINTR
))
{
/* Try again later */
}
else
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
NULL
);
return
REDIS_ERR
;
}
int
nwritten
=
(
c
->
flags
&
REDIS_SSL
)
?
redisSslWrite
(
c
)
:
rawWrite
(
c
);
if
(
nwritten
<
0
)
{
return
REDIS_ERR
;
}
else
if
(
nwritten
>
0
)
{
if
(
nwritten
==
(
signed
)
sdslen
(
c
->
obuf
))
{
sdsfree
(
c
->
obuf
);
...
...
hiredis.h
View file @
297de989
...
...
@@ -74,6 +74,15 @@
/* Flag that is set when we should set SO_REUSEADDR before calling bind() */
#define REDIS_REUSEADDR 0x80
/* Flag that is set when this connection is done through SSL */
#define REDIS_SSL 0x100
/**
* Flag that indicates the user does not want the context to
* be automatically freed upon error
*/
#define REDIS_NO_AUTO_FREE 0x200
#define REDIS_KEEPALIVE_INTERVAL 15
/* seconds */
/* number of times we retry to connect in the case of EADDRNOTAVAIL and
...
...
@@ -109,9 +118,59 @@ void redisFreeSdsCommand(sds cmd);
enum
redisConnectionType
{
REDIS_CONN_TCP
,
REDIS_CONN_UNIX
REDIS_CONN_UNIX
,
REDIS_CONN_USERFD
};
struct
redisSsl
;
#define REDIS_OPT_NONBLOCK 0x01
#define REDIS_OPT_REUSEADDR 0x02
/**
* Don't automatically free the async object on a connection failure,
* or other implicit conditions. Only free on an explicit call to disconnect() or free()
*/
#define REDIS_OPT_NOAUTOFREE 0x04
typedef
struct
{
/*
* the type of connection to use. This also indicates which
* `endpoint` member field to use
*/
int
type
;
/* bit field of REDIS_OPT_xxx */
int
options
;
/* timeout value. if NULL, no timeout is used */
const
struct
timeval
*
timeout
;
union
{
/** use this field for tcp/ip connections */
struct
{
const
char
*
source_addr
;
const
char
*
ip
;
int
port
;
}
tcp
;
/** use this field for unix domain sockets */
const
char
*
unix_socket
;
/**
* use this field to have hiredis operate an already-open
* file descriptor */
int
fd
;
}
endpoint
;
}
redisOptions
;
/**
* Helper macros to initialize options to their specified fields.
*/
#define REDIS_OPTIONS_SET_TCP(opts, ip_, port_) \
(opts)->type = REDIS_CONN_TCP; \
(opts)->endpoint.tcp.ip = ip_; \
(opts)->endpoint.tcp.port = port_;
#define REDIS_OPTIONS_SET_UNIX(opts, path) \
(opts)->type = REDIS_CONN_UNIX; \
(opts)->endpoint.unix_socket = path;
/* Context for a connection to Redis */
typedef
struct
redisContext
{
int
err
;
/* Error flags, 0 when there is no error */
...
...
@@ -137,8 +196,12 @@ typedef struct redisContext {
/* For non-blocking connect */
struct
sockadr
*
saddr
;
size_t
addrlen
;
/* For SSL communication */
struct
redisSsl
*
ssl
;
}
redisContext
;
redisContext
*
redisConnectWithOptions
(
const
redisOptions
*
options
);
redisContext
*
redisConnect
(
const
char
*
ip
,
int
port
);
redisContext
*
redisConnectWithTimeout
(
const
char
*
ip
,
int
port
,
const
struct
timeval
tv
);
redisContext
*
redisConnectNonBlock
(
const
char
*
ip
,
int
port
);
...
...
@@ -151,6 +214,13 @@ redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval
redisContext
*
redisConnectUnixNonBlock
(
const
char
*
path
);
redisContext
*
redisConnectFd
(
int
fd
);
/**
* Secure the connection using SSL. This should be done before any command is
* executed on the connection.
*/
int
redisSecureConnection
(
redisContext
*
c
,
const
char
*
capath
,
const
char
*
certpath
,
const
char
*
keypath
,
const
char
*
servername
);
/**
* Reconnect the given context using the saved information.
*
...
...
net.c
View file @
297de989
...
...
@@ -502,7 +502,7 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
sa
=
(
struct
sockaddr_un
*
)(
c
->
saddr
=
malloc
(
sizeof
(
struct
sockaddr_un
)));
c
->
addrlen
=
sizeof
(
struct
sockaddr_un
);
sa
->
sun_family
=
AF_UNIX
;
strncpy
(
sa
->
sun_path
,
path
,
sizeof
(
sa
->
sun_path
)
-
1
);
strncpy
(
sa
->
sun_path
,
path
,
sizeof
(
sa
->
sun_path
)
-
1
);
if
(
connect
(
c
->
fd
,
(
struct
sockaddr
*
)
sa
,
sizeof
(
*
sa
))
==
-
1
)
{
if
(
errno
==
EINPROGRESS
&&
!
blocking
)
{
/* This is ok. */
...
...
read.h
View file @
297de989
...
...
@@ -45,6 +45,7 @@
#define REDIS_ERR_EOF 3
/* End of file */
#define REDIS_ERR_PROTOCOL 4
/* Protocol error */
#define REDIS_ERR_OOM 5
/* Out of memory */
#define REDIS_ERR_TIMEOUT 6
/* Timed out */
#define REDIS_ERR_OTHER 2
/* Everything else... */
#define REDIS_REPLY_STRING 1
...
...
sslio.c
0 → 100644
View file @
297de989
#include "hiredis.h"
#include "sslio.h"
#include <assert.h>
#ifdef HIREDIS_SSL
#include <pthread.h>
void
__redisSetError
(
redisContext
*
c
,
int
type
,
const
char
*
str
);
/**
* Callback used for debugging
*/
static
void
sslLogCallback
(
const
SSL
*
ssl
,
int
where
,
int
ret
)
{
const
char
*
retstr
=
""
;
int
should_log
=
1
;
/* Ignore low-level SSL stuff */
if
(
where
&
SSL_CB_ALERT
)
{
should_log
=
1
;
}
if
(
where
==
SSL_CB_HANDSHAKE_START
||
where
==
SSL_CB_HANDSHAKE_DONE
)
{
should_log
=
1
;
}
if
((
where
&
SSL_CB_EXIT
)
&&
ret
==
0
)
{
should_log
=
1
;
}
if
(
!
should_log
)
{
return
;
}
retstr
=
SSL_alert_type_string
(
ret
);
printf
(
"ST(0x%x). %s. R(0x%x)%s
\n
"
,
where
,
SSL_state_string_long
(
ssl
),
ret
,
retstr
);
if
(
where
==
SSL_CB_HANDSHAKE_DONE
)
{
printf
(
"Using SSL version %s. Cipher=%s
\n
"
,
SSL_get_version
(
ssl
),
SSL_get_cipher_name
(
ssl
));
}
}
typedef
pthread_mutex_t
sslLockType
;
static
void
sslLockInit
(
sslLockType
*
l
)
{
pthread_mutex_init
(
l
,
NULL
);
}
static
void
sslLockAcquire
(
sslLockType
*
l
)
{
pthread_mutex_lock
(
l
);
}
static
void
sslLockRelease
(
sslLockType
*
l
)
{
pthread_mutex_unlock
(
l
);
}
static
pthread_mutex_t
*
ossl_locks
;
static
void
opensslDoLock
(
int
mode
,
int
lkid
,
const
char
*
f
,
int
line
)
{
sslLockType
*
l
=
ossl_locks
+
lkid
;
if
(
mode
&
CRYPTO_LOCK
)
{
sslLockAcquire
(
l
);
}
else
{
sslLockRelease
(
l
);
}
(
void
)
f
;
(
void
)
line
;
}
static
void
initOpensslLocks
(
void
)
{
unsigned
ii
,
nlocks
;
if
(
CRYPTO_get_locking_callback
()
!=
NULL
)
{
/* Someone already set the callback before us. Don't destroy it! */
return
;
}
nlocks
=
CRYPTO_num_locks
();
ossl_locks
=
malloc
(
sizeof
(
*
ossl_locks
)
*
nlocks
);
for
(
ii
=
0
;
ii
<
nlocks
;
ii
++
)
{
sslLockInit
(
ossl_locks
+
ii
);
}
CRYPTO_set_locking_callback
(
opensslDoLock
);
}
void
redisFreeSsl
(
redisSsl
*
ssl
){
if
(
ssl
->
ctx
)
{
SSL_CTX_free
(
ssl
->
ctx
);
}
if
(
ssl
->
ssl
)
{
SSL_free
(
ssl
->
ssl
);
}
free
(
ssl
);
}
int
redisSslCreate
(
redisContext
*
c
,
const
char
*
capath
,
const
char
*
certpath
,
const
char
*
keypath
,
const
char
*
servername
)
{
assert
(
!
c
->
ssl
);
c
->
ssl
=
calloc
(
1
,
sizeof
(
*
c
->
ssl
));
static
int
isInit
=
0
;
if
(
!
isInit
)
{
isInit
=
1
;
SSL_library_init
();
initOpensslLocks
();
}
redisSsl
*
s
=
c
->
ssl
;
s
->
ctx
=
SSL_CTX_new
(
SSLv23_client_method
());
SSL_CTX_set_info_callback
(
s
->
ctx
,
sslLogCallback
);
SSL_CTX_set_mode
(
s
->
ctx
,
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
);
SSL_CTX_set_options
(
s
->
ctx
,
SSL_OP_NO_SSLv2
|
SSL_OP_NO_SSLv3
);
SSL_CTX_set_verify
(
s
->
ctx
,
SSL_VERIFY_PEER
,
NULL
);
if
((
certpath
!=
NULL
&&
keypath
==
NULL
)
||
(
keypath
!=
NULL
&&
certpath
==
NULL
))
{
__redisSetError
(
c
,
REDIS_ERR
,
"certpath and keypath must be specified together"
);
return
REDIS_ERR
;
}
if
(
capath
)
{
if
(
!
SSL_CTX_load_verify_locations
(
s
->
ctx
,
capath
,
NULL
))
{
__redisSetError
(
c
,
REDIS_ERR
,
"Invalid CA certificate"
);
return
REDIS_ERR
;
}
}
if
(
certpath
)
{
if
(
!
SSL_CTX_use_certificate_chain_file
(
s
->
ctx
,
certpath
))
{
__redisSetError
(
c
,
REDIS_ERR
,
"Invalid client certificate"
);
return
REDIS_ERR
;
}
if
(
!
SSL_CTX_use_PrivateKey_file
(
s
->
ctx
,
keypath
,
SSL_FILETYPE_PEM
))
{
__redisSetError
(
c
,
REDIS_ERR
,
"Invalid client key"
);
return
REDIS_ERR
;
}
}
s
->
ssl
=
SSL_new
(
s
->
ctx
);
if
(
!
s
->
ssl
)
{
__redisSetError
(
c
,
REDIS_ERR
,
"Couldn't create new SSL instance"
);
return
REDIS_ERR
;
}
if
(
servername
)
{
if
(
!
SSL_set_tlsext_host_name
(
s
->
ssl
,
servername
))
{
__redisSetError
(
c
,
REDIS_ERR
,
"Couldn't set server name indication"
);
return
REDIS_ERR
;
}
}
SSL_set_fd
(
s
->
ssl
,
c
->
fd
);
SSL_set_connect_state
(
s
->
ssl
);
c
->
flags
|=
REDIS_SSL
;
int
rv
=
SSL_connect
(
c
->
ssl
->
ssl
);
if
(
rv
==
1
)
{
return
REDIS_OK
;
}
rv
=
SSL_get_error
(
s
->
ssl
,
rv
);
if
(((
c
->
flags
&
REDIS_BLOCK
)
==
0
)
&&
(
rv
==
SSL_ERROR_WANT_READ
||
rv
==
SSL_ERROR_WANT_WRITE
))
{
return
REDIS_OK
;
}
if
(
c
->
err
==
0
)
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
"SSL_connect() failed"
);
}
return
REDIS_ERR
;
}
static
int
maybeCheckWant
(
redisSsl
*
rssl
,
int
rv
)
{
/**
* If the error is WANT_READ or WANT_WRITE, the appropriate flags are set
* and true is returned. False is returned otherwise
*/
if
(
rv
==
SSL_ERROR_WANT_READ
)
{
rssl
->
wantRead
=
1
;
return
1
;
}
else
if
(
rv
==
SSL_ERROR_WANT_WRITE
)
{
rssl
->
pendingWrite
=
1
;
return
1
;
}
else
{
return
0
;
}
}
int
redisSslRead
(
redisContext
*
c
,
char
*
buf
,
size_t
bufcap
)
{
int
nread
=
SSL_read
(
c
->
ssl
->
ssl
,
buf
,
bufcap
);
if
(
nread
>
0
)
{
return
nread
;
}
else
if
(
nread
==
0
)
{
__redisSetError
(
c
,
REDIS_ERR_EOF
,
"Server closed the connection"
);
return
-
1
;
}
else
{
int
err
=
SSL_get_error
(
c
->
ssl
->
ssl
,
nread
);
if
(
maybeCheckWant
(
c
->
ssl
,
err
))
{
return
0
;
}
else
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
NULL
);
return
-
1
;
}
}
}
int
redisSslWrite
(
redisContext
*
c
)
{
size_t
len
=
c
->
ssl
->
lastLen
?
c
->
ssl
->
lastLen
:
sdslen
(
c
->
obuf
);
int
rv
=
SSL_write
(
c
->
ssl
->
ssl
,
c
->
obuf
,
len
);
if
(
rv
>
0
)
{
c
->
ssl
->
lastLen
=
0
;
}
else
if
(
rv
<
0
)
{
c
->
ssl
->
lastLen
=
len
;
int
err
=
SSL_get_error
(
c
->
ssl
->
ssl
,
rv
);
if
(
maybeCheckWant
(
c
->
ssl
,
err
))
{
return
0
;
}
else
{
__redisSetError
(
c
,
REDIS_ERR_IO
,
NULL
);
return
-
1
;
}
}
return
rv
;
}
#endif
sslio.h
0 → 100644
View file @
297de989
#ifndef REDIS_SSLIO_H
#define REDIS_SSLIO_H
#ifndef HIREDIS_SSL
typedef
struct
redisSsl
{
size_t
lastLen
;
int
wantRead
;
int
pendingWrite
;
}
redisSsl
;
static
inline
void
redisFreeSsl
(
redisSsl
*
ssl
)
{
(
void
)
ssl
;
}
static
inline
int
redisSslCreate
(
struct
redisContext
*
c
,
const
char
*
ca
,
const
char
*
cert
,
const
char
*
key
,
const
char
*
servername
)
{
(
void
)
c
;(
void
)
ca
;(
void
)
cert
;(
void
)
key
;(
void
)
servername
;
return
REDIS_ERR
;
}
static
inline
int
redisSslRead
(
struct
redisContext
*
c
,
char
*
s
,
size_t
n
)
{
(
void
)
c
;(
void
)
s
;(
void
)
n
;
return
-
1
;
}
static
inline
int
redisSslWrite
(
struct
redisContext
*
c
)
{
(
void
)
c
;
return
-
1
;
}
#else
#include <openssl/ssl.h>
/**
* This file contains routines for HIREDIS' SSL
*/
typedef
struct
redisSsl
{
SSL
*
ssl
;
SSL_CTX
*
ctx
;
/**
* SSL_write() requires to be called again with the same arguments it was
* previously called with in the event of an SSL_read/SSL_write situation
*/
size_t
lastLen
;
/** Whether the SSL layer requires read (possibly before a write) */
int
wantRead
;
/**
* Whether a write was requested prior to a read. If set, the write()
* should resume whenever a read takes place, if possible
*/
int
pendingWrite
;
}
redisSsl
;
struct
redisContext
;
void
redisFreeSsl
(
redisSsl
*
);
int
redisSslCreate
(
struct
redisContext
*
c
,
const
char
*
caPath
,
const
char
*
certPath
,
const
char
*
keyPath
,
const
char
*
servername
);
int
redisSslRead
(
struct
redisContext
*
c
,
char
*
buf
,
size_t
bufcap
);
int
redisSslWrite
(
struct
redisContext
*
c
);
#endif
/* HIREDIS_SSL */
#endif
/* HIREDIS_SSLIO_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment