28 #include <freeradius-devel/redis/io.h>
29 #include <freeradius-devel/util/debug.h>
31 #include <hiredis/async.h>
52 DEBUG4(
"Signalled by hiredis, connection disconnected");
64 DEBUG4(
"Signalled by hiredis, connection is open");
77 DEBUG4(
"redis handle %p - FD %i now readable", h, fd);
79 redisAsyncHandleRead(h->
ac);
90 DEBUG4(
"redis handle %p - FD %i now writable", h, fd);
92 redisAsyncHandleWrite(h->
ac);
99 int fd_errno,
void *
uctx)
117 redisContext *c = &(h->
ac->c);
126 if (!read && !write) {
127 DEBUG4(
"redis handle %p - De-registering FD %i", h, c->fd);
130 PERROR(
"redis handle %p - De-registration failed for FD %i", h, c->fd);
135 DEBUG4(
"redis handle %p - Registered for %s%serror events on FD %i",
136 h, read ?
"read+" :
"", write ?
"write+" :
"", c->fd);
143 PERROR(
"redis handle %p - Registration failed for %s%serror events on FD %i",
144 h, read ?
"read+" :
"", write ?
"write+" :
"", c->fd);
196 #ifdef HAVE_REDIS_TIMEOUT
205 DEBUG4(
"redis handle %p - Timeout", h);
207 redisAsyncHandleTimeout(h->
ac);
213 static void _redis_io_timer_modify(
void *
uctx,
struct timeval tv)
224 timeout, _redis_io_service_timer_expired, conn) < 0) {
225 PERROR(
"redis timeout %p - Failed adding timeout", h);
253 DEBUG4(
"redis handle %p - Freed", h);
263 if (ac->ev.data != NULL)
return REDIS_ERR;
269 #ifdef HAVE_REDIS_TIMEOUT
270 ac->ev.scheduleTimer = _redis_io_timer_modify;
273 memcpy(&ac->ev.data, &conn,
sizeof(ac->ev.data));
288 if (h->
ac) redisAsyncFree(h->
ac);
309 char const *host =
conf->hostname;
321 h->
ac = redisAsyncConnect(host, port);
323 ERROR(
"Failed allocating handle for %s:%u", host, port);
328 ERROR(
"Failed allocating handle for %s:%u: %s", host, port, h->
ac->errstr);
330 redisAsyncFree(h->
ac);
341 memcpy(&h->
ac->data, &conn,
sizeof(h->
ac->data));
369 if (ret != REDIS_OK) {
370 ERROR(
"Failed setting connected callback: Error %i", ret);
374 ERROR(
"Failed setting disconnected callback: Error %i", ret);
390 redisAsyncDisconnect(our_h->
ac);
424 char const *log_prefix)
436 .init = _redis_io_connection_init,
443 if (!conn)
return NULL;
@ CONNECTION_STATE_FAILED
Connection has failed.
@ CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
@ CONNECTION_STATE_SHUTDOWN
Connection is shutting down.
@ CONNECTION_FAILED
Connection is being reconnected because it failed.
Holds a complete set of functions for a connection.
fr_dcursor_eval_t void const * uctx
static fr_time_delta_t timeout
#define fr_dlist_talloc_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
#define fr_event_fd_insert(...)
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
#define fr_event_timer_in(...)
static void _redis_io_service_errored(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, int fd_errno, void *uctx)
Redis FD errored - Automatically removes registered events.
static void _redis_io_del_write(void *uctx)
De-register FD for writes.
static void _redis_io_del_read(void *uctx)
De-register FD for reads.
static int _redis_handle_free(fr_redis_handle_t *h)
Free the redis async context when the handle is freed.
static void _redis_io_add_write(void *uctx)
Register FD for writes.
static connection_state_t _redis_io_connection_shutdown(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
Gracefully signal that the connection should shutdown.
static void _redis_io_service_writable(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Redis FD became writable.
static void _redis_io_free(void *uctx)
Handle freeing the redisAsyncContext.
static void _redis_io_service_readable(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Redis FD became readable.
connection_t * fr_redis_connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, connection_conf_t const *conn_conf, fr_redis_io_conf_t const *io_conf, char const *log_prefix)
Allocate an async redis I/O connection.
static void _redis_connected(redisAsyncContext const *ac, UNUSED int status)
Called by hiredis to indicate the connection is live.
static void _redis_io_add_read(void *uctx)
Register FD for reads.
static int fr_redis_io_setup(redisAsyncContext *ac, connection_t const *conn)
Configures async I/O callbacks for an existing redisAsyncContext.
CC_NO_UBSAN(function)
Callback for the initialise state.
static void _redis_disconnected(redisAsyncContext const *ac, UNUSED int status)
Called by hiredis to indicate the connection is dead.
redisAsyncContext * fr_redis_connection_get_async_ctx(connection_t *conn)
Return the redisAsyncContext associated with the connection.
static void _redis_io_common(connection_t *conn, fr_redis_handle_t *h, bool read, bool write)
Deal with the method hiredis uses to register/unregister interest in a file descriptor.
static void _redis_io_connection_close(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
Notification that the connection has errored and must be closed.
bool read_set
We're listening for reads.
redisAsyncContext * ac
Async handle for hiredis.
fr_event_timer_t const * timer
Connection timer.
fr_dlist_head_t ignore
Contains SQNs for responses that should be ignored.
bool ignore_disconnect_cb
Ensure that redisAsyncFree doesn't cause a callback loop.
bool write_set
We're listening for writes.
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Stores all information relating to an event list.
void connection_signal_reconnect(connection_t *conn, connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
connection_t * connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, connection_funcs_t const *funcs, connection_conf_t const *conf, char const *log_prefix, void const *uctx)
Allocate a new connection.
void connection_signal_connected(connection_t *conn)
Asynchronously signal that the connection is open.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define talloc_get_type_abort_const
static fr_time_delta_t fr_time_delta_from_timeval(struct timeval const *tv)
A time delta, a difference in time measured in nanoseconds.
static fr_event_list_t * el
#define fr_box_time_delta(_val)