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
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);
}
/**
}
}
+/**
+ * @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
*/
bool async_post_error(struct async_req *req, struct tevent_context *ev,
- uint32_t error)
+ uint64_t error)
{
req->error = error;
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,
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);
}
*/
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
};
/**
* 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
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);
#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));
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)
NTSTATUS async_req_simple_recv_ntstatus(struct async_req *req);
-bool async_req_ntnomem(const void *p, struct async_req *req);
-
#endif
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,
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;
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;
}
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;
}
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;
}
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;
}
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;
}
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;
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;
}
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;
}
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 = 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 = 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;
}
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;
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;
}
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;
}
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;
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;
}
state->start_offset + state->requested,
request_thistime);
- if (async_req_ntnomem(new_req, state->req)) {
+ if (async_req_nomem(new_req, state->req)) {
return;
}
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;
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;
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;
}
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;
}
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;
*/
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);
/* 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;
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;
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;
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;
}
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;
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;