diff --git a/lib/async_req/async_req.c b/lib/async_req/async_req.c index 1b9fc5517be..db47bd93ed1 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); } /** @@ -129,6 +130,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 @@ -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 19b052a788a..fc849880cd6 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 dd810260743..65bc0f6510a 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)) { - *status = NT_STATUS(error); - return true; + if (!async_req_is_error(req, &state, &error)) { + return false; } - 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) diff --git a/lib/async_req/async_req_ntstatus.h b/lib/async_req/async_req_ntstatus.h index 7cc8caa14c8..7555aac6035 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 diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index bafcdc5c5c6..78431d93c89 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1077,7 +1077,7 @@ static void open_socket_out_connected(struct async_req *subreq) subreq = async_connect_send(state, state->ev, state->fd, (struct sockaddr *)&state->ss, state->salen); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } if (!async_req_set_timeout(subreq, state->ev, @@ -1209,7 +1209,7 @@ static void open_socket_out_defer_waited(struct async_req *subreq) subreq = open_socket_out_send(state, state->ev, &state->ss, state->port, state->timeout); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = open_socket_out_defer_connected; diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index 7bca627690a..e779e47d282 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -96,7 +96,7 @@ static void wb_req_read_len(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, sizeof(struct winbindd_request) - sizeof(uint32), 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -135,7 +135,7 @@ static void wb_req_read_main(struct async_req *subreq) state->wb_req->extra_data.data = TALLOC_ARRAY( state->wb_req, char, state->wb_req->extra_len + 1); - if (async_req_ntnomem(state->wb_req->extra_data.data, req)) { + if (async_req_nomem(state->wb_req->extra_data.data, req)) { return; } @@ -144,7 +144,7 @@ static void wb_req_read_main(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, state->wb_req->extra_data.data, state->wb_req->extra_len, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -244,7 +244,7 @@ static void wb_req_write_main(struct async_req *subreq) subreq = sendall_send(state, state->ev, state->fd, state->wb_req->extra_data.data, state->wb_req->extra_len, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -343,7 +343,7 @@ static void wb_resp_read_len(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, sizeof(struct winbindd_response) - sizeof(uint32), 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -375,7 +375,7 @@ static void wb_resp_read_main(struct async_req *subreq) state->wb_resp->extra_data.data = TALLOC_ARRAY( state->wb_resp, char, extra_len+1); - if (async_req_ntnomem(state->wb_resp->extra_data.data, req)) { + if (async_req_nomem(state->wb_resp->extra_data.data, req)) { return; } ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; @@ -383,7 +383,7 @@ static void wb_resp_read_main(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, state->wb_resp->extra_data.data, extra_len, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -484,7 +484,7 @@ static void wb_resp_write_main(struct async_req *subreq) state, state->ev, state->fd, state->wb_resp->extra_data.data, state->wb_resp->length - sizeof(struct winbindd_response), 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index cf5ce7e734f..f22b96a99a9 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -463,7 +463,7 @@ static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, &state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -496,7 +496,7 @@ static void wb_open_pipe_ping_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, &state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -526,7 +526,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq) subreq = wb_connect_send(state, state->ev, state->wb_ctx, (char *)wb_resp->extra_data.data); TALLOC_FREE(wb_resp); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -582,7 +582,7 @@ static void wb_trigger_trans(struct async_req *req) subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, state->need_priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = wb_trans_connect_done; @@ -592,7 +592,7 @@ static void wb_trigger_trans(struct async_req *req) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = wb_trans_done; @@ -665,7 +665,7 @@ static bool wb_trans_retry(struct async_req *req, } subreq = async_wait_send(state, state->ev, timeval_set(1, 0)); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return true; } @@ -691,7 +691,7 @@ static void wb_trans_retry_wait_done(struct async_req *subreq) subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, state->need_priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = wb_trans_connect_done; @@ -715,7 +715,7 @@ static void wb_trans_connect_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 26fa614f69c..9d17ff86a5e 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -432,7 +432,7 @@ static void cli_pull_read_done(struct async_req *read_req) state->start_offset + state->requested, request_thistime); - if (async_req_ntnomem(new_req, state->req)) { + if (async_req_nomem(new_req, state->req)) { return; } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index b9fd3224851..2841ff08f61 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -269,7 +269,7 @@ static void rpc_read_done(struct async_req *subreq) state->data + state->num_read, state->size - state->num_read, state->transport->priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = rpc_read_done; @@ -350,7 +350,7 @@ static void rpc_write_done(struct async_req *subreq) state->data + state->num_written, state->size - state->num_written, state->transport->priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = rpc_write_done; @@ -512,7 +512,7 @@ static void get_complete_frag_got_header(struct async_req *subreq) state, state->ev, state->cli->transport, (uint8_t *)(prs_data_p(state->pdu) + RPC_HEADER_LEN), state->prhdr->frag_len - RPC_HEADER_LEN); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = get_complete_frag_got_rest; @@ -1138,7 +1138,7 @@ static void cli_api_pipe_write_done(struct async_req *subreq) } state->rdata = TALLOC_ARRAY(state, uint8_t, RPC_HEADER_LEN); - if (async_req_ntnomem(state->rdata, req)) { + if (async_req_nomem(state->rdata, req)) { return; } @@ -1150,7 +1150,7 @@ static void cli_api_pipe_write_done(struct async_req *subreq) subreq = state->transport->read_send(state, state->ev, state->rdata, RPC_HEADER_LEN, state->transport->priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = cli_api_pipe_read_done; @@ -1336,7 +1336,7 @@ static void rpc_api_pipe_trans_done(struct async_req *subreq) */ rdata_copy = (char *)memdup(rdata, rdata_len); TALLOC_FREE(rdata); - if (async_req_ntnomem(rdata_copy, req)) { + if (async_req_nomem(rdata_copy, req)) { return; } prs_give_memory(&state->incoming_frag, rdata_copy, rdata_len, true); @@ -1344,7 +1344,7 @@ static void rpc_api_pipe_trans_done(struct async_req *subreq) /* Ensure we have enough data for a pdu. */ subreq = get_complete_frag_send(state, state->ev, state->cli, &state->rhdr, &state->incoming_frag); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = rpc_api_pipe_got_pdu; @@ -1436,7 +1436,7 @@ static void rpc_api_pipe_got_pdu(struct async_req *subreq) subreq = get_complete_frag_send(state, state->ev, state->cli, &state->rhdr, &state->incoming_frag); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = rpc_api_pipe_got_pdu; @@ -2235,7 +2235,7 @@ static void rpc_api_pipe_req_write_done(struct async_req *subreq) subreq = rpc_api_pipe_send(state, state->ev, state->cli, &state->outgoing_frag, RPC_RESPONSE); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = rpc_api_pipe_req_done; @@ -2246,7 +2246,7 @@ static void rpc_api_pipe_req_write_done(struct async_req *subreq) state->cli->transport, (uint8_t *)prs_data_p(&state->outgoing_frag), prs_offset(&state->outgoing_frag)); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = rpc_api_pipe_req_write_done; diff --git a/source3/rpc_client/rpc_transport_smbd.c b/source3/rpc_client/rpc_transport_smbd.c index b93e4cf6023..bf4aa65daec 100644 --- a/source3/rpc_client/rpc_transport_smbd.c +++ b/source3/rpc_client/rpc_transport_smbd.c @@ -174,7 +174,7 @@ static void get_anon_ipc_negprot_done(struct async_req *subreq) } subreq = cli_session_setup_guest_send(state, state->ev, state->cli); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = get_anon_ipc_sesssetup_done; @@ -198,7 +198,7 @@ static void get_anon_ipc_sesssetup_done(struct async_req *subreq) subreq = cli_tcon_andx_send(state, state->ev, state->cli, "IPC$", "IPC", NULL, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = get_anon_ipc_tcon_done;