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);
 
  213static 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)
 
  443        if (!conn) 
return NULL;
 
 
#define CC_NO_UBSAN(_sanitize)
@ 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.
#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/.
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.
redisAsyncContext * fr_redis_connection_get_async_ctx(connection_t *conn)
Return the redisAsyncContext associated with the connection.
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 connection_state_t _redis_io_connection_init(void **h_out, connection_t *conn, void *uctx)
Callback for the initialise state.
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.
static void _redis_connected(redisAsyncContext const *ac, UNUSED int status)
Called by hiredis to indicate the connection is live.
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_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.
static void _redis_disconnected(redisAsyncContext const *ac, UNUSED int status)
Called by hiredis to indicate the connection is dead.
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_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.
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)