summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/async_req/async_sock.c300
-rw-r--r--lib/async_req/async_sock.h11
-rw-r--r--lib/tevent/tevent.h14
-rw-r--r--lib/tevent/tevent_req.c42
4 files changed, 53 insertions, 314 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 3563421e0e..40e7bca4c8 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -30,45 +30,6 @@
#endif
/**
- * Discriminator for async_syscall_state
- */
-enum async_syscall_type {
- ASYNC_SYSCALL_SEND,
- ASYNC_SYSCALL_RECV,
-};
-
-/**
- * Holder for syscall arguments and the result
- */
-
-struct async_syscall_state {
- enum async_syscall_type syscall_type;
- struct tevent_fd *fde;
-
- union {
- struct param_send {
- int fd;
- const void *buffer;
- size_t length;
- int flags;
- } param_send;
- struct param_recv {
- int fd;
- void *buffer;
- size_t length;
- int flags;
- } param_recv;
- } param;
-
- union {
- ssize_t result_ssize_t;
- size_t result_size_t;
- int result_int;
- } result;
- int sys_errno;
-};
-
-/**
* @brief Map async_req states to unix-style errnos
* @param[in] req The async req to get the state from
* @param[out] err Pointer to take the unix-style errno
@@ -117,267 +78,6 @@ int async_req_simple_recv_errno(struct async_req *req)
return 0;
}
-/**
- * @brief Create a new async syscall req
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] type Which syscall will this be
- * @param[in] pstate Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state. The async_syscall_state will be put
- * into the async_req as private_data.
- */
-
-static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- enum async_syscall_type type,
- struct async_syscall_state **pstate)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- if (!async_req_setup(mem_ctx, &result, &state,
- struct async_syscall_state)) {
- return NULL;
- }
- state->syscall_type = type;
-
- result->private_data = state;
-
- *pstate = state;
-
- return result;
-}
-
-/**
- * @brief Create a new async syscall req based on a fd
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] type Which syscall will this be
- * @param[in] fd The file descriptor we work on
- * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in?
- * @param[in] fde_cb The callback function for the file descriptor event
- * @param[in] pstate Where to put the newly created private_data state
- * @retval The new request
- *
- * This is a helper function to prepare a new struct async_req with an
- * associated struct async_syscall_state and an associated file descriptor
- * event.
- */
-
-static struct async_req *async_fde_syscall_new(
- TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- enum async_syscall_type type,
- int fd,
- uint16_t fde_flags,
- void (*fde_cb)(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv),
- struct async_syscall_state **pstate)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_syscall_new(mem_ctx, ev, type, &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result);
- if (state->fde == NULL) {
- TALLOC_FREE(result);
- return NULL;
- }
- *pstate = state;
- return result;
-}
-
-/**
- * Retrieve a ssize_t typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_ssize_t;
-}
-
-/**
- * Retrieve a size_t typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_size_t;
-}
-
-/**
- * Retrieve a int typed result from an async syscall
- * @param[in] req The syscall that has just finished
- * @param[out] perrno Where to put the syscall's errno
- * @retval The return value from the asynchronously called syscall
- */
-
-int async_syscall_result_int(struct async_req *req, int *perrno)
-{
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
-
- *perrno = state->sys_errno;
- return state->result.result_int;
-}
-
-/**
- * fde event handler for the "send" syscall
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the send
- * @param[in] flags Can only be TEVENT_FD_WRITE here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_send_callback(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_send *p = &state->param.param_send;
-
- if (state->syscall_type != ASYNC_SYSCALL_SEND) {
- async_req_error(req, EIO);
- return;
- }
-
- state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
- p->flags);
- state->sys_errno = errno;
-
- TALLOC_FREE(state->fde);
-
- async_req_done(req);
-}
-
-/**
- * Async version of send(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to send to
- * @param[in] buffer The buffer to send
- * @param[in] length How many bytes to send
- * @param[in] flags flags passed to send(2)
- *
- * This function is a direct counterpart of send(2)
- */
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, const void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_SEND,
- fd, TEVENT_FD_WRITE, async_send_callback,
- &state);
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_send.fd = fd;
- state->param.param_send.buffer = buffer;
- state->param.param_send.length = length;
- state->param.param_send.flags = flags;
-
- return result;
-}
-
-/**
- * fde event handler for the "recv" syscall
- * @param[in] ev The event context that sent us here
- * @param[in] fde The file descriptor event associated with the recv
- * @param[in] flags Can only be TEVENT_FD_READ here
- * @param[in] priv private data, "struct async_req *" in this case
- */
-
-static void async_recv_callback(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
-{
- struct async_req *req = talloc_get_type_abort(
- priv, struct async_req);
- struct async_syscall_state *state = talloc_get_type_abort(
- req->private_data, struct async_syscall_state);
- struct param_recv *p = &state->param.param_recv;
-
- if (state->syscall_type != ASYNC_SYSCALL_RECV) {
- async_req_error(req, EIO);
- return;
- }
-
- state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
- p->flags);
- state->sys_errno = errno;
-
- TALLOC_FREE(state->fde);
-
- async_req_done(req);
-}
-
-/**
- * Async version of recv(2)
- * @param[in] mem_ctx The memory context to hang the result off
- * @param[in] ev The event context to work from
- * @param[in] fd The socket to recv from
- * @param[in] buffer The buffer to recv into
- * @param[in] length How many bytes to recv
- * @param[in] flags flags passed to recv(2)
- *
- * This function is a direct counterpart of recv(2)
- */
-
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, void *buffer, size_t length,
- int flags)
-{
- struct async_req *result;
- struct async_syscall_state *state;
-
- result = async_fde_syscall_new(
- mem_ctx, ev, ASYNC_SYSCALL_RECV,
- fd, TEVENT_FD_READ, async_recv_callback,
- &state);
-
- if (result == NULL) {
- return NULL;
- }
-
- state->param.param_recv.fd = fd;
- state->param.param_recv.buffer = buffer;
- state->param.param_recv.length = length;
- state->param.param_recv.flags = flags;
-
- return result;
-}
-
struct async_send_state {
int fd;
const void *buf;
diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h
index bfc4346d39..e001709d27 100644
--- a/lib/async_req/async_sock.h
+++ b/lib/async_req/async_sock.h
@@ -25,17 +25,6 @@
bool async_req_is_errno(struct async_req *req, int *err);
int async_req_simple_recv_errno(struct async_req *req);
-ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno);
-size_t async_syscall_result_size_t(struct async_req *req, int *perrno);
-int async_syscall_result_int(struct async_req *req, int *perrno);
-
-struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, const void *buffer, size_t length,
- int flags);
-struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- int fd, void *buffer, size_t length,
- int flags);
-
struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
int fd, const void *buf, size_t len,
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index b3d1c6d59a..185a8fa193 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -212,6 +212,15 @@ struct tevent_req {
void *private_state;
/**
+ * @brief A function to overwrite the default print function
+ *
+ * The implementation doing the work may want to imeplement a
+ * custom function to print the text representation of the async
+ * request.
+ */
+ char *(*private_print)(struct tevent_req *req, TALLOC_CTX *mem_ctx);
+
+ /**
* @brief Internal state of the request
*
* Callers should only access this via functions and never directly.
@@ -267,6 +276,8 @@ struct tevent_req {
} internal;
};
+char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx);
+
char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req);
struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx,
@@ -296,6 +307,9 @@ struct tevent_req *tevent_req_post(struct tevent_req *req,
bool tevent_req_is_in_progress(struct tevent_req *req);
+bool tevent_req_poll(struct tevent_req *req,
+ struct tevent_context *ev);
+
bool tevent_req_is_error(struct tevent_req *req,
enum tevent_req_state *state,
uint64_t *error);
diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c
index 800e3855d1..e243c7de5d 100644
--- a/lib/tevent/tevent_req.c
+++ b/lib/tevent/tevent_req.c
@@ -28,14 +28,17 @@
#include "tevent_util.h"
/**
- * @brief Print an tevent_req structure in debug messages
- * @param[in] mem_ctx The memory context for the result
+ * @brief The default print function for creating debug messages
* @param[in] req The request to be printed
+ * @param[in] mem_ctx The memory context for the result
* @retval Text representation of req
*
+ * The function should not be used by users of the asynx API,
+ * but custom print function can use it and append custom text
+ * to the string.
*/
-char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
+char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx)
{
return talloc_asprintf(mem_ctx,
"tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] "
@@ -51,6 +54,24 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
}
/**
+ * @brief Print an tevent_req structure in debug messages
+ * @param[in] mem_ctx The memory context for the result
+ * @param[in] req The request to be printed
+ * @retval Text representation of req
+ *
+ * This function should be used by callers of the async API
+ */
+
+char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req)
+{
+ if (!req->private_print) {
+ return tevent_req_default_print(req, mem_ctx);
+ }
+
+ return req->private_print(req, mem_ctx);
+}
+
+/**
* @brief Create an async request
* @param[in] mem_ctx The memory context for the result
* @param[in] ev The event context this async request will be driven by
@@ -235,6 +256,21 @@ bool tevent_req_is_in_progress(struct tevent_req *req)
return false;
}
+bool tevent_req_poll(struct tevent_req *req,
+ struct tevent_context *ev)
+{
+ while (tevent_req_is_in_progress(req)) {
+ int ret;
+
+ ret = tevent_loop_once(ev);
+ if (ret != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state,
uint64_t *error)
{