Add a user-defined callback to set custom socket options.

Fixes #698
This commit is contained in:
michael-grunder 2022-09-07 14:24:30 -07:00
parent 855b48a819
commit 1bcf402445
3 changed files with 24 additions and 0 deletions

View File

@ -829,6 +829,9 @@ redisContext *redisConnectWithOptions(const redisOptions *options) {
c->flags |= REDIS_PREFER_IPV6;
}
/* Set any configured socket callback function */
c->socket_cb = options->socket_cb;
/* Set any user supplied RESP3 PUSH handler or use freeReplyObject
* as a default unless specifically flagged that we don't want one. */
if (options->push_cb != NULL)

View File

@ -216,6 +216,10 @@ typedef struct {
redisFD fd;
} endpoint;
/* Socket callback function executed after socket creation but before
* we connect. This can be used to set OS specific socket options. */
int (*socket_cb)(redisFD fd, void *privdata, char **errstr);
/* Optional user defined data/destructor */
void *privdata;
void (*free_privdata)(void *);
@ -239,6 +243,10 @@ typedef struct {
(opts)->endpoint.unix_socket = path; \
} while(0)
#define REDIS_OPTIONS_SET_SOCKET_CB(opts, cb) do { \
(opts)->socket_cb = cb; \
} while(0)
#define REDIS_OPTIONS_SET_PRIVDATA(opts, data, dtor) do { \
(opts)->privdata = data; \
(opts)->free_privdata = dtor; \
@ -288,6 +296,11 @@ typedef struct redisContext {
struct sockaddr *saddr;
size_t addrlen;
/* A callback to be invoked after successful socket creation but before we
* connect. This can be usefull for setting OS specific socket flags.
* The callback may optionally set errstr in the event of an error. */
int (*socket_cb)(redisFD fd, void *privdata, char **errstr);
/* Optional data and corresponding destructor users can use to provide
* context to a given redisContext. Not used by hiredis. */
void *privdata;

8
net.c
View File

@ -402,6 +402,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
int rv, n;
char _port[6]; /* strlen("65535"); */
struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
char *errstr;
int blocking = (c->flags & REDIS_BLOCK);
int reuseaddr = (c->flags & REDIS_REUSEADDR);
int reuses = 0;
@ -477,6 +478,13 @@ addrretry:
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == REDIS_INVALID_FD)
continue;
/* Invoke any user-provided socket callback */
errstr = NULL;
if (c->socket_cb && c->socket_cb(s, c->privdata, &errstr) != REDIS_OK) {
__redisSetError(c, REDIS_ERR_OTHER, errstr ? errstr : "Failure in user-defined socket callback");
goto error;
}
c->fd = s;
if (redisSetBlocking(c,0) != REDIS_OK)
goto error;