diff options
Diffstat (limited to 'lib/async_req')
-rw-r--r-- | lib/async_req/async_req.c | 297 | ||||
-rw-r--r-- | lib/async_req/async_req.h | 158 | ||||
-rw-r--r-- | lib/async_req/async_req_ntstatus.c | 70 | ||||
-rw-r--r-- | lib/async_req/async_req_ntstatus.h | 35 | ||||
-rw-r--r-- | lib/async_req/async_sock.c | 53 | ||||
-rw-r--r-- | lib/async_req/async_sock.h | 3 | ||||
-rw-r--r-- | lib/async_req/config.mk | 2 |
7 files changed, 3 insertions, 615 deletions
diff --git a/lib/async_req/async_req.c b/lib/async_req/async_req.c deleted file mode 100644 index 4dfe809738..0000000000 --- a/lib/async_req/async_req.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Infrastructure for async requests - Copyright (C) Volker Lendecke 2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/tevent/tevent.h" -#include "lib/talloc/talloc.h" -#include "lib/util/dlinklist.h" -#include "lib/async_req/async_req.h" - -#ifndef TALLOC_FREE -#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) -#endif - -/** - * @brief Print an async_req structure - * @param[in] mem_ctx The memory context for the result - * @param[in] req The request to be printed - * @retval Text representation of req - * - * This is a default print function for async requests. Implementations should - * override this with more specific information. - * - * This function should not be used by async API users, this is non-static - * only to allow implementations to easily provide default information in - * their specific functions. - */ - -char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req) -{ - return talloc_asprintf(mem_ctx, "async_req: state=%d, error=%d, " - "priv=%s", req->state, (int)req->error, - talloc_get_name(req->private_data)); -} - -/** - * @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 - * @retval A new async request - * - * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS - */ - -struct async_req *async_req_new(TALLOC_CTX *mem_ctx) -{ - struct async_req *result; - - result = talloc_zero(mem_ctx, struct async_req); - if (result == NULL) { - return NULL; - } - result->state = ASYNC_REQ_IN_PROGRESS; - result->print = async_req_print; - return result; -} - -static void async_req_finish(struct async_req *req, enum async_req_state state) -{ - req->state = state; - if (req->async.fn != NULL) { - req->async.fn(req); - } -} - -/** - * @brief An async request has successfully finished - * @param[in] req The finished request - * - * async_req_done is to be used by implementors of async requests. When a - * request is successfully finished, this function calls the user's completion - * function. - */ - -void async_req_done(struct async_req *req) -{ - async_req_finish(req, ASYNC_REQ_DONE); -} - -/** - * @brief An async request has seen an error - * @param[in] req The request with an error - * @param[in] error The error code - * - * async_req_done is to be used by implementors of async requests. When a - * request can not successfully completed, the implementation should call this - * function with the appropriate status code. - */ - -void async_req_error(struct async_req *req, uint64_t error) -{ - req->error = error; - async_req_finish(req, ASYNC_REQ_USER_ERROR); -} - -/** - * @brief Timed event callback - * @param[in] ev Event context - * @param[in] te The timed event - * @param[in] now zero time - * @param[in] priv The async request to be finished - */ - -static void async_trigger(struct tevent_context *ev, struct tevent_timer *te, - struct timeval now, void *priv) -{ - struct async_req *req = talloc_get_type_abort(priv, struct async_req); - - TALLOC_FREE(te); - if (req->error == 0) { - async_req_done(req); - } - else { - async_req_error(req, req->error); - } -} - -/** - * @brief Helper function for nomem check - * @param[in] p The pointer to be checked - * @param[in] req The request being processed - * - * Convenience helper to easily check alloc failure within a callback - * implementing the next step of an async request. - * - * Call pattern would be - * \code - * p = talloc(mem_ctx, bla); - * if (async_req_ntnomem(p, req)) { - * return; - * } - * \endcode - */ - -bool async_req_nomem(const void *p, struct async_req *req) -{ - if (p != NULL) { - return false; - } - async_req_finish(req, ASYNC_REQ_NO_MEMORY); - return true; -} - -/** - * @brief Finish a request before it started processing - * @param[in] req The finished request - * @param[in] status The success code - * - * An implementation of an async request might find that it can either finish - * the request without waiting for an external event, or it can't even start - * the engine. To present the illusion of a callback to the user of the API, - * the implementation can call this helper function which triggers an - * immediate timed event. This way the caller can use the same calling - * conventions, independent of whether the request was actually deferred. - */ - -bool async_post_error(struct async_req *req, struct tevent_context *ev, - uint64_t error) -{ - req->error = error; - - if (tevent_add_timer(ev, req, tevent_timeval_zero(), - async_trigger, req) == NULL) { - return false; - } - return true; -} - -bool async_req_is_error(struct async_req *req, enum async_req_state *state, - uint64_t *error) -{ - if (req->state == ASYNC_REQ_DONE) { - return false; - } - if (req->state == ASYNC_REQ_USER_ERROR) { - *error = req->error; - } - *state = req->state; - return true; -} - -struct async_queue_entry { - struct async_queue_entry *prev, *next; - struct async_req_queue *queue; - struct async_req *req; - void (*trigger)(struct async_req *req); -}; - -struct async_req_queue { - struct async_queue_entry *queue; -}; - -struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx) -{ - return talloc_zero(mem_ctx, struct async_req_queue); -} - -static int async_queue_entry_destructor(struct async_queue_entry *e) -{ - struct async_req_queue *queue = e->queue; - - DLIST_REMOVE(queue->queue, e); - - if (queue->queue != NULL) { - queue->queue->trigger(queue->queue->req); - } - - return 0; -} - -static void async_req_immediate_trigger(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval now, - void *priv) -{ - struct async_queue_entry *e = talloc_get_type_abort( - priv, struct async_queue_entry); - - TALLOC_FREE(te); - e->trigger(e->req); -} - -bool async_req_enqueue(struct async_req_queue *queue, struct tevent_context *ev, - struct async_req *req, - void (*trigger)(struct async_req *req)) -{ - struct async_queue_entry *e; - bool busy; - - busy = (queue->queue != NULL); - - e = talloc(req, struct async_queue_entry); - if (e == NULL) { - return false; - } - - e->req = req; - e->trigger = trigger; - e->queue = queue; - - DLIST_ADD_END(queue->queue, e, struct async_queue_entry *); - talloc_set_destructor(e, async_queue_entry_destructor); - - if (!busy) { - struct tevent_timer *te; - - te = tevent_add_timer(ev, e, tevent_timeval_zero(), - async_req_immediate_trigger, - e); - if (te == NULL) { - TALLOC_FREE(e); - return false; - } - } - - return true; -} - -bool _async_req_setup(TALLOC_CTX *mem_ctx, struct async_req **preq, - void *pstate, size_t state_size, const char *typename) -{ - struct async_req *req; - void **ppstate = (void **)pstate; - void *state; - - req = async_req_new(mem_ctx); - if (req == NULL) { - return false; - } - state = talloc_size(req, state_size); - if (state == NULL) { - TALLOC_FREE(req); - return false; - } - talloc_set_name_const(state, typename); - req->private_data = state; - - *preq = req; - *ppstate = state; - - return true; -} diff --git a/lib/async_req/async_req.h b/lib/async_req/async_req.h deleted file mode 100644 index fdec1b708e..0000000000 --- a/lib/async_req/async_req.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Infrastructure for async requests - Copyright (C) Volker Lendecke 2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ASYNC_REQ_H__ -#define __ASYNC_REQ_H__ - -#include "lib/talloc/talloc.h" - -/** - * An async request moves between the following 4 states: - */ - -enum async_req_state { - /** - * we are creating the request - */ - ASYNC_REQ_INIT, - /** - * we are waiting the request to complete - */ - ASYNC_REQ_IN_PROGRESS, - /** - * the request is finished - */ - ASYNC_REQ_DONE, - /** - * A user error has occured - */ - ASYNC_REQ_USER_ERROR, - /** - * Request timed out - */ - ASYNC_REQ_TIMED_OUT, - /** - * No memory in between - */ - ASYNC_REQ_NO_MEMORY -}; - -/** - * @brief An async request - * - * This represents an async request being processed by callbacks via an event - * context. A user can issue for example a write request to a socket, giving - * an implementation function the fd, the buffer and the number of bytes to - * transfer. The function issuing the request will immediately return without - * blocking most likely without having sent anything. The API user then fills - * in req->async.fn and req->async.priv, functions that are called when the - * request is finished. - * - * It is up to the user of the async request to talloc_free it after it has - * finished. This can happen while the completion function is called. - */ - -struct async_req { - /** - * @brief The external state - will be queried by the caller - * - * While the async request is being processed, state will remain in - * ASYNC_REQ_IN_PROGRESS. A request is finished if - * req->state>=ASYNC_REQ_DONE. - */ - enum async_req_state state; - - /** - * @brief Private pointer for the actual implementation - * - * The implementation doing the work for the async request needs a - * current state like for example a fd event. The user of an async - * request should not touch this. - */ - void *private_data; - - /** - * @brief Print yourself, for debugging purposes - * - * Async requests are opaque data structures. The implementation of an - * async request can define a custom function to print more debug - * info. - */ - char *(*print)(TALLOC_CTX *mem_ctx, struct async_req *); - - /** - * @brief status code when finished - * - * This status can be queried in the async completion function. It - * will be set to 0 when everything went fine. - **/ - uint64_t error; - - /** - * @brief What to do on completion - * - * This is used for the user of an async request, fn is called when - * the request completes, either successfully or with an error. - */ - struct { - /** - * @brief Completion function - * Completion function, to be filled by the API user - */ - void (*fn)(struct async_req *); - /** - * @brief Private data for the completion function - */ - void *priv; - } async; -}; - -struct async_req *async_req_new(TALLOC_CTX *mem_ctx); - -char *async_req_print(TALLOC_CTX *mem_ctx, struct async_req *req); - -void async_req_done(struct async_req *req); - -void async_req_error(struct async_req *req, uint64_t error); - -bool async_req_nomem(const void *p, struct async_req *req); - -bool async_post_error(struct async_req *req, struct tevent_context *ev, - uint64_t error); - -bool async_req_is_error(struct async_req *req, enum async_req_state *state, - uint64_t *error); - -struct async_req_queue; - -struct async_req_queue *async_req_queue_init(TALLOC_CTX *mem_ctx); - -bool async_req_enqueue(struct async_req_queue *queue, - struct tevent_context *ev, - struct async_req *req, - void (*trigger)(struct async_req *req)); - -bool _async_req_setup(TALLOC_CTX *mem_ctx, struct async_req **preq, - void *pstate, size_t state_size, const char *typename); - -#define async_req_setup(_mem_ctx, _preq, _pstate, type) \ - _async_req_setup((_mem_ctx), (_preq), (_pstate), sizeof(type), #type) - - -#endif diff --git a/lib/async_req/async_req_ntstatus.c b/lib/async_req/async_req_ntstatus.c deleted file mode 100644 index 65bc0f6510..0000000000 --- a/lib/async_req/async_req_ntstatus.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NTSTATUS wrappers for async_req.h - Copyright (C) Volker Lendecke 2008, 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/tevent/tevent.h" -#include "lib/talloc/talloc.h" -#include "lib/util/dlinklist.h" -#include "lib/async_req/async_req_ntstatus.h" - -void async_req_nterror(struct async_req *req, NTSTATUS status) -{ - async_req_error(req, NT_STATUS_V(status)); -} - -bool async_post_ntstatus(struct async_req *req, struct tevent_context *ev, - NTSTATUS status) -{ - return async_post_error(req, ev, NT_STATUS_V(status)); -} - -bool async_req_is_nterror(struct async_req *req, NTSTATUS *status) -{ - enum async_req_state state; - uint64_t error; - - if (!async_req_is_error(req, &state, &error)) { - return false; - } - switch (state) { - case ASYNC_REQ_USER_ERROR: - *status = NT_STATUS(error); - break; - case ASYNC_REQ_TIMED_OUT: - *status = NT_STATUS_IO_TIMEOUT; - break; - case ASYNC_REQ_NO_MEMORY: - *status = NT_STATUS_NO_MEMORY; - break; - default: - *status = NT_STATUS_INTERNAL_ERROR; - break; - } - return true; -} - -NTSTATUS async_req_simple_recv_ntstatus(struct async_req *req) -{ - NTSTATUS status; - - if (async_req_is_nterror(req, &status)) { - return status; - } - return NT_STATUS_OK; -} diff --git a/lib/async_req/async_req_ntstatus.h b/lib/async_req/async_req_ntstatus.h deleted file mode 100644 index 7555aac603..0000000000 --- a/lib/async_req/async_req_ntstatus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Unix SMB/CIFS implementation. - NTSTATUS wrappers for async_req.h - Copyright (C) Volker Lendecke 2008, 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __ASYNC_REQ_NTSTATUS_H__ -#define __ASYNC_REQ_NTSTATUS_H__ - -#include "lib/async_req/async_req.h" -#include "includes.h" - -void async_req_nterror(struct async_req *req, NTSTATUS status); - -bool async_post_ntstatus(struct async_req *req, struct tevent_context *ev, - NTSTATUS status); - -bool async_req_is_nterror(struct async_req *req, NTSTATUS *status); - -NTSTATUS async_req_simple_recv_ntstatus(struct async_req *req); - -#endif diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index 77df406044..543972815d 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -20,7 +20,6 @@ #include "includes.h" #include "lib/talloc/talloc.h" #include "lib/tevent/tevent.h" -#include "lib/async_req/async_req.h" #include "lib/async_req/async_sock.h" #include "lib/util/tevent_unix.h" #include <fcntl.h> @@ -29,55 +28,6 @@ #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) #endif -/** - * @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 - * - * @return true if the async_req is in an error state, false otherwise - */ - -bool async_req_is_errno(struct async_req *req, int *err) -{ - enum async_req_state state; - uint64_t error; - - if (!async_req_is_error(req, &state, &error)) { - return false; - } - - switch (state) { - case ASYNC_REQ_USER_ERROR: - *err = (int)error; - break; - case ASYNC_REQ_TIMED_OUT: -#ifdef ETIMEDOUT - *err = ETIMEDOUT; -#else - *err = EAGAIN; -#endif - break; - case ASYNC_REQ_NO_MEMORY: - *err = ENOMEM; - break; - default: - *err = EIO; - break; - } - return true; -} - -int async_req_simple_recv_errno(struct async_req *req) -{ - int err; - - if (async_req_is_errno(req, &err)) { - return err; - } - - return 0; -} - struct async_send_state { int fd; const void *buf; @@ -547,7 +497,8 @@ static void read_packet_handler(struct tevent_context *ev, ssize_t nread, more; uint8_t *tmp; - nread = read(state->fd, state->buf+state->nread, total-state->nread); + nread = recv(state->fd, state->buf+state->nread, total-state->nread, + 0); if (nread == -1) { tevent_req_error(req, errno); return; diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h index c5d9400eb6..ec859dc0ae 100644 --- a/lib/async_req/async_sock.h +++ b/lib/async_req/async_sock.h @@ -22,9 +22,6 @@ #include "includes.h" -bool async_req_is_errno(struct async_req *req, int *err); -int async_req_simple_recv_errno(struct async_req *req); - 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/async_req/config.mk b/lib/async_req/config.mk index 820f890fd0..bf0fd6a2db 100644 --- a/lib/async_req/config.mk +++ b/lib/async_req/config.mk @@ -1,3 +1,3 @@ [SUBSYSTEM::LIBASYNC_REQ] -LIBASYNC_REQ_OBJ_FILES = $(addprefix ../lib/async_req/, async_req.o async_sock.o async_req_ntstatus.o) +LIBASYNC_REQ_OBJ_FILES = $(addprefix ../lib/async_req/, async_sock.o) |