summaryrefslogtreecommitdiff
path: root/source3/libsmb/clientgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/clientgen.c')
-rw-r--r--source3/libsmb/clientgen.c145
1 files changed, 66 insertions, 79 deletions
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 450a7cf4cd..45addc2163 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -805,90 +805,72 @@ bool cli_send_keepalive(struct cli_state *cli)
return true;
}
-/**
- * @brief: Collect a echo reply
- * @param[in] req The corresponding async request
- *
- * There might be more than one echo reply. This helper pulls the reply out of
- * the data stream. If all expected replies have arrived, declare the
- * async_req done.
- */
-
-static void cli_echo_recv_helper(struct async_req *req)
-{
- struct cli_request *cli_req;
- uint8_t wct;
- uint16_t *vwv;
- uint16_t num_bytes;
- uint8_t *bytes;
- NTSTATUS status;
+struct cli_echo_state {
+ uint16_t vwv[1];
+ DATA_BLOB data;
+ int num_echos;
+};
- status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes);
- if (!NT_STATUS_IS_OK(status)) {
- async_req_nterror(req, status);
- return;
- }
+static void cli_echo_done(struct tevent_req *subreq);
- cli_req = talloc_get_type_abort(req->private_data, struct cli_request);
+struct tevent_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct cli_state *cli, uint16_t num_echos,
+ DATA_BLOB data)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_echo_state *state;
- if ((num_bytes != cli_req->data.echo.data.length)
- || (memcmp(cli_req->data.echo.data.data, bytes,
- num_bytes) != 0)) {
- async_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
+ req = tevent_req_create(mem_ctx, &state, struct cli_echo_state);
+ if (req == NULL) {
+ return NULL;
}
+ SSVAL(state->vwv, 0, num_echos);
+ state->data = data;
+ state->num_echos = num_echos;
- cli_req->data.echo.num_echos -= 1;
-
- if (cli_req->data.echo.num_echos == 0) {
- async_req_done(req);
- return;
+ subreq = cli_smb_send(state, ev, cli, SMBecho, 0, 1, state->vwv,
+ data.length, data.data);
+ if (subreq == NULL) {
+ goto fail;
}
-
- return;
+ tevent_req_set_callback(subreq, cli_echo_done, req);
+ return req;
+ fail:
+ TALLOC_FREE(req);
+ return NULL;
}
-/**
- * @brief Send SMBEcho requests
- * @param[in] mem_ctx The memory context to put the async_req on
- * @param[in] ev The event context that will call us back
- * @param[in] cli The connection to send the echo to
- * @param[in] num_echos How many times do we want to get the reply?
- * @param[in] data The data we want to get back
- * @retval The async request
- */
-
-struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
- struct cli_state *cli, uint16_t num_echos,
- DATA_BLOB data)
+static void cli_echo_done(struct tevent_req *subreq)
{
- uint16_t vwv[1];
- uint8_t *data_copy;
- struct async_req *result;
- struct cli_request *req;
-
- SSVAL(vwv, 0, num_echos);
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_echo_state *state = tevent_req_data(
+ req, struct cli_echo_state);
+ NTSTATUS status;
+ uint32_t num_bytes;
+ uint8_t *bytes;
- data_copy = (uint8_t *)talloc_memdup(mem_ctx, data.data, data.length);
- if (data_copy == NULL) {
- return NULL;
+ status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
}
-
- result = cli_request_send(mem_ctx, ev, cli, SMBecho, 0, 1, vwv, 0,
- data.length, data.data);
- if (result == NULL) {
- TALLOC_FREE(data_copy);
- return NULL;
+ if ((num_bytes != state->data.length)
+ || (memcmp(bytes, state->data.data, num_bytes) != 0)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
}
- req = talloc_get_type_abort(result->private_data, struct cli_request);
-
- req->data.echo.num_echos = num_echos;
- req->data.echo.data.data = talloc_move(req, &data_copy);
- req->data.echo.data.length = data.length;
- req->recv_helper.fn = cli_echo_recv_helper;
+ state->num_echos -=1;
+ if (state->num_echos == 0) {
+ tevent_req_done(req);
+ return;
+ }
- return result;
+ if (!cli_smb_req_set_pending(subreq)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
}
/**
@@ -897,9 +879,9 @@ struct async_req *cli_echo_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
* @retval Did the server reply correctly?
*/
-NTSTATUS cli_echo_recv(struct async_req *req)
+NTSTATUS cli_echo_recv(struct tevent_req *req)
{
- return async_req_simple_recv_ntstatus(req);
+ return tevent_req_simple_recv_ntstatus(req);
}
/**
@@ -916,35 +898,40 @@ NTSTATUS cli_echo(struct cli_state *cli, uint16_t num_echos, DATA_BLOB data)
{
TALLOC_CTX *frame = talloc_stackframe();
struct event_context *ev;
- struct async_req *req;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
- if (cli->fd_event != NULL) {
+ if (cli_has_async_calls(cli)) {
/*
* Can't use sync call while an async call is in flight
*/
- cli_set_error(cli, NT_STATUS_INVALID_PARAMETER);
+ status = NT_STATUS_INVALID_PARAMETER;
goto fail;
}
ev = event_context_init(frame);
if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
req = cli_echo_send(frame, ev, cli, num_echos, data);
if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- while (req->state < ASYNC_REQ_DONE) {
- event_loop_once(ev);
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
}
status = cli_echo_recv(req);
-
fail:
TALLOC_FREE(frame);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
return status;
}