summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h5
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c124
2 files changed, 107 insertions, 22 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index b308e86af7..ca10b7097f 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6320,6 +6320,11 @@ struct async_req *np_write_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
NTSTATUS np_write_recv(struct async_req *req, ssize_t *nwritten);
NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data,
size_t len, ssize_t *nwritten);
+struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct fake_file_handle *handle,
+ uint8_t *data, size_t len);
+NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread,
+ bool *is_data_outstanding);
NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len,
ssize_t *nread, bool *is_data_outstanding);
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index b5b6bbd6eb..6e2bfb8b4a 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -1224,38 +1224,118 @@ NTSTATUS np_write(struct fake_file_handle *handle, const uint8_t *data,
return status;
}
-NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len,
- ssize_t *nread, bool *is_data_outstanding)
+struct np_read_state {
+ ssize_t nread;
+ bool is_data_outstanding;
+};
+
+static void np_read_done(struct async_req *subreq);
+
+struct async_req *np_read_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
+ struct fake_file_handle *handle,
+ uint8_t *data, size_t len)
{
- switch (handle->type) {
- case FAKE_FILE_TYPE_NAMED_PIPE: {
+ struct async_req *result, *subreq;
+ struct np_read_state *state;
+ NTSTATUS status;
+
+ if (!async_req_setup(mem_ctx, &result, &state,
+ struct np_read_state)) {
+ return NULL;
+ }
+
+ if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE) {
struct pipes_struct *p = talloc_get_type_abort(
handle->private_data, struct pipes_struct);
- *nread = read_from_internal_pipe(p, (char *)data, len,
- is_data_outstanding);
- break;
+
+ state->nread = read_from_internal_pipe(
+ p, (char *)data, len, &state->is_data_outstanding);
+
+ status = (state->nread >= 0)
+ ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
+ goto post_status;
}
- case FAKE_FILE_TYPE_NAMED_PIPE_PROXY: {
+
+ if (handle->type == FAKE_FILE_TYPE_NAMED_PIPE_PROXY) {
struct np_proxy_state *p = talloc_get_type_abort(
handle->private_data, struct np_proxy_state);
- int available = 0;
- *nread = sys_read(p->fd, (char *)data, len);
+ state->nread = len;
- /*
- * We don't look at the ioctl result. We don't really care
- * if there is data available, because this is racy anyway.
- */
- ioctl(p->fd, FIONREAD, &available);
- *is_data_outstanding = (available > 0);
+ subreq = recvall_send(state, ev, p->fd, data, len, 0);
+ if (subreq == NULL) {
+ goto fail;
+ }
+ subreq->async.fn = np_read_done;
+ subreq->async.priv = result;
+ return result;
+ }
+
+ status = NT_STATUS_INVALID_HANDLE;
+ post_status:
+ if (async_post_status(result, ev, status)) {
+ return result;
+ }
+ fail:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static void np_read_done(struct async_req *subreq)
+{
+ struct async_req *req = talloc_get_type_abort(
+ subreq->async.priv, struct async_req);
+ NTSTATUS status;
+
+ status = recvall_recv(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ async_req_error(req, status);
+ return;
+ }
+ async_req_done(req);
+}
+
+NTSTATUS np_read_recv(struct async_req *req, ssize_t *nread,
+ bool *is_data_outstanding)
+{
+ struct np_read_state *state = talloc_get_type_abort(
+ req->private_data, struct np_read_state);
+ NTSTATUS status;
+
+ if (async_req_is_error(req, &status)) {
+ return status;
+ }
+ *nread = state->nread;
+ *is_data_outstanding = state->is_data_outstanding;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS np_read(struct fake_file_handle *handle, uint8_t *data, size_t len,
+ ssize_t *nread, bool *is_data_outstanding)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct async_req *req;
+ NTSTATUS status;
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
- break;
+ req = np_read_send(frame, ev, handle, data, len);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
- default:
- return NT_STATUS_INVALID_HANDLE;
- break;
+
+ while (req->state < ASYNC_REQ_DONE) {
+ event_loop_once(ev);
}
- return ((*nread) >= 0)
- ? NT_STATUS_OK : NT_STATUS_UNEXPECTED_IO_ERROR;
+ status = np_read_recv(req, nread, is_data_outstanding);
+ fail:
+ TALLOC_FREE(frame);
+ return status;
}