#ifndef SOCK_FD_H
#define SOCK_FD_H
/**
* @file
*
* A generic sock_stream implementation for normal POSIX file descriptor based byte streams.
*/
#include "sock_internal.h"
#include <event2/event.h>
#include <stdbool.h>
/**
* The fd-based sock_stream base implementation
*/
struct sock_fd {
/** The base struct for sock_stream_* functions */
struct sock_stream base;
/** The OS file descriptor */
int fd;
/** The callback and arg used for sock_fd_init_ev - required for sock_fd_set */
void (*ev_cb) (evutil_socket_t, short, void *);
void *ev_arg;
/** The IO events */
struct event *ev_read, *ev_write;
};
/**
* Get a sock_stream pointer from a sock_fd
*/
#define SOCK_FD_BASE(sock_ptr) (&(sock_ptr)->base)
/**
* Get the sock_stream.err pointer from a sock_fd
*/
#define SOCK_FD_ERR(sock_ptr) SOCK_ERR(SOCK_FD_BASE(sock_ptr))
/**
* Callback suitable for use with sock_fd_init_ev, which just invoke's the sock_stream's callbacks as appropriate.
*/
void sock_fd_event_handler (evutil_socket_t fd, short what, void *arg);
/**
* sock_stream_methods::read implementation.
*/
err_t sock_fd_read (struct sock_stream *base_sock, void *buf, size_t *len, struct error_info *err);
/**
* sock_stream_methods::write implementation.
*/
err_t sock_fd_write (struct sock_stream *base_sock, const void *buf, size_t *len, struct error_info *err);
/**
* sock_stream_methods::event_init implementation.
*/
err_t sock_fd_event_init (struct sock_stream *base_sock);
/**
* sock_stream_methods::event_enable implementation.
*/
err_t sock_fd_event_enable (struct sock_stream *base_sock, short mask);
/**
* Initialize the sock_fd with the given fd, or -1, if no valid fd yet.
*/
void sock_fd_init (struct sock_fd *sock, int fd);
/**
* Set the socket's nonblock mode. This should not do anything (apart from an extraneous syscall) if non-blocking
* mode is already set.
*/
err_t sock_fd_set_nonblock (struct sock_fd *sock, bool nonblock);
/**
* Initialize sock_fd.ev_* to use the socket's fd with the given callback. The ev's are not activated yet.
*
* The sock_fd must *not* have any ev's set.
*/
err_t sock_fd_init_ev (struct sock_fd *sock, void (*ev_cb) (evutil_socket_t, short, void *), void *arg);
/**
* event_add the specified ev_* events, so they are enabled and the callback will be executed.
*/
err_t sock_fd_enable_events (struct sock_fd *sock, short mask);
/**
* The opposite of init_ev, this clears any set events, so that they can be re-initialized with init_ev.
*/
void sock_fd_deinit_ev (struct sock_fd *sock);
/**
* Update a sock_fd's fd, also updating any events set with sock_fd_init_ev. If any events were enabled before, they
* are not enabled anymore.
*/
err_t sock_fd_set (struct sock_fd *sock, int fd);
/**
* Close an opened sock_fd, restoring it to a state suitable for sock_fd_init
*/
err_t sock_fd_close (struct sock_fd *sock);
#endif