diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/async_req/async_req.c | 75 | ||||
-rw-r--r-- | lib/async_req/async_req.h | 23 | ||||
-rw-r--r-- | lib/async_req/async_req_ntstatus.c | 48 | ||||
-rw-r--r-- | lib/async_req/async_req_ntstatus.h | 2 |
4 files changed, 86 insertions, 62 deletions
diff --git a/lib/async_req/async_req.c b/lib/async_req/async_req.c index 1b9fc5517b..db47bd93ed 100644 --- a/lib/async_req/async_req.c +++ b/lib/async_req/async_req.c @@ -70,6 +70,14 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx) 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 @@ -81,30 +89,23 @@ struct async_req *async_req_new(TALLOC_CTX *mem_ctx) void async_req_done(struct async_req *req) { - req->error = 0; - req->state = ASYNC_REQ_DONE; - if (req->async.fn != NULL) { - req->async.fn(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] status The error code + * @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, uint32_t error) +void async_req_error(struct async_req *req, uint64_t error) { req->error = error; - req->state = ASYNC_REQ_ERROR; - if (req->async.fn != NULL) { - req->async.fn(req); - } + async_req_finish(req, ASYNC_REQ_USER_ERROR); } /** @@ -130,6 +131,32 @@ static void async_trigger(struct tevent_context *ev, struct tevent_timer *te, } /** + * @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 @@ -143,7 +170,7 @@ static void async_trigger(struct tevent_context *ev, struct tevent_timer *te, */ bool async_post_error(struct async_req *req, struct tevent_context *ev, - uint32_t error) + uint64_t error) { req->error = error; @@ -154,16 +181,17 @@ bool async_post_error(struct async_req *req, struct tevent_context *ev, return true; } -bool async_req_is_error(struct async_req *req, uint32_t *error) +bool async_req_is_error(struct async_req *req, enum async_req_state *state, + uint64_t *error) { - if (req->state < ASYNC_REQ_DONE) { - return true; + if (req->state == ASYNC_REQ_DONE) { + return false; } - if (req->state == ASYNC_REQ_ERROR) { + if (req->state == ASYNC_REQ_USER_ERROR) { *error = req->error; - return true; } - return false; + *state = req->state; + return true; } static void async_req_timedout(struct tevent_context *ev, @@ -171,18 +199,17 @@ static void async_req_timedout(struct tevent_context *ev, struct timeval now, void *priv) { - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); + struct async_req *req = talloc_get_type_abort(priv, struct async_req); TALLOC_FREE(te); - async_req_nterror(req, NT_STATUS_IO_TIMEOUT); + async_req_finish(req, ASYNC_REQ_TIMED_OUT); } bool async_req_set_timeout(struct async_req *req, struct tevent_context *ev, struct timeval to) { - return (tevent_add_timer(ev, req, - timeval_current_ofs(to.tv_sec, to.tv_usec), - async_req_timedout, req) + return (tevent_add_timer( + ev, req, timeval_current_ofs(to.tv_sec, to.tv_usec), + async_req_timedout, req) != NULL); } diff --git a/lib/async_req/async_req.h b/lib/async_req/async_req.h index 19b052a788..fc849880cd 100644 --- a/lib/async_req/async_req.h +++ b/lib/async_req/async_req.h @@ -40,9 +40,17 @@ enum async_req_state { */ ASYNC_REQ_DONE, /** - * an error has occured + * A user error has occured */ - ASYNC_REQ_ERROR + ASYNC_REQ_USER_ERROR, + /** + * Request timed out + */ + ASYNC_REQ_TIMED_OUT, + /** + * No memory in between + */ + ASYNC_REQ_NO_MEMORY }; /** @@ -94,7 +102,7 @@ struct async_req { * This status can be queried in the async completion function. It * will be set to 0 when everything went fine. **/ - uint32_t error; + uint64_t error; /** * @brief What to do on completion @@ -121,12 +129,15 @@ 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, uint32_t error); +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, - uint32_t error); + uint64_t error); -bool async_req_is_error(struct async_req *req, uint32_t *error); +bool async_req_is_error(struct async_req *req, enum async_req_state *state, + uint64_t *error); bool async_req_set_timeout(struct async_req *req, struct tevent_context *ev, struct timeval to); diff --git a/lib/async_req/async_req_ntstatus.c b/lib/async_req/async_req_ntstatus.c index dd81026074..65bc0f6510 100644 --- a/lib/async_req/async_req_ntstatus.c +++ b/lib/async_req/async_req_ntstatus.c @@ -23,32 +23,6 @@ #include "lib/util/dlinklist.h" #include "lib/async_req/async_req_ntstatus.h" -/** - * @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_ntnomem(const void *p, struct async_req *req) -{ - if (p != NULL) { - return false; - } - async_req_nterror(req, NT_STATUS_NO_MEMORY); - return true; -} - void async_req_nterror(struct async_req *req, NTSTATUS status) { async_req_error(req, NT_STATUS_V(status)); @@ -62,13 +36,27 @@ bool async_post_ntstatus(struct async_req *req, struct tevent_context *ev, bool async_req_is_nterror(struct async_req *req, NTSTATUS *status) { - uint32_t error = NT_STATUS_V(NT_STATUS_INTERNAL_ERROR); + enum async_req_state state; + uint64_t error; - if (async_req_is_error(req, &error)) { + if (!async_req_is_error(req, &state, &error)) { + return false; + } + switch (state) { + case ASYNC_REQ_USER_ERROR: *status = NT_STATUS(error); - return true; + 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 false; + return true; } NTSTATUS async_req_simple_recv_ntstatus(struct async_req *req) diff --git a/lib/async_req/async_req_ntstatus.h b/lib/async_req/async_req_ntstatus.h index 7cc8caa14c..7555aac603 100644 --- a/lib/async_req/async_req_ntstatus.h +++ b/lib/async_req/async_req_ntstatus.h @@ -32,6 +32,4 @@ bool async_req_is_nterror(struct async_req *req, NTSTATUS *status); NTSTATUS async_req_simple_recv_ntstatus(struct async_req *req); -bool async_req_ntnomem(const void *p, struct async_req *req); - #endif |