libcli/util: add tstream_read_pdu_blob_send/recv
authorStefan Metzmacher <metze@samba.org>
Thu, 5 Nov 2009 08:55:12 +0000 (09:55 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 8 Jan 2010 13:36:43 +0000 (14:36 +0100)
This will take the some full_request callback function
as the Samba4 packet code.

metze

libcli/util/tstream.c [new file with mode: 0644]
libcli/util/tstream.h [new file with mode: 0644]
source4/libcli/config.mk

diff --git a/libcli/util/tstream.c b/libcli/util/tstream.c
new file mode 100644 (file)
index 0000000..f6c92f3
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  Copyright (C) Stefan Metzmacher 2009
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include <tevent.h>
+#include "system/filesys.h"
+#include "../lib/tsocket/tsocket.h"
+#include "../libcli/util/tstream.h"
+#include "../lib/util/tevent_ntstatus.h"
+
+struct tstream_read_pdu_blob_state {
+       /* this structs are owned by the caller */
+       struct {
+               struct tevent_context *ev;
+               struct tstream_context *stream;
+               NTSTATUS (*full_fn)(void *private_data,
+                                   DATA_BLOB blob,
+                                   size_t *packet_size);
+               void *full_private;
+       } caller;
+
+       DATA_BLOB pdu_blob;
+       struct iovec tmp_vector;
+};
+
+static void tstream_read_pdu_blob_done(struct tevent_req *subreq);
+
+struct tevent_req *tstream_read_pdu_blob_send(TALLOC_CTX *mem_ctx,
+                               struct tevent_context *ev,
+                               struct tstream_context *stream,
+                               size_t initial_read_size,
+                               NTSTATUS (*full_fn)(void *private_data,
+                                                   DATA_BLOB blob,
+                                                   size_t *packet_size),
+                               void *full_private)
+{
+       struct tevent_req *req;
+       struct tstream_read_pdu_blob_state *state;
+       struct tevent_req *subreq;
+       uint8_t *buf;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct tstream_read_pdu_blob_state);
+       if (!req) {
+               return NULL;
+       }
+
+       state->caller.ev                = ev;
+       state->caller.stream            = stream;
+       state->caller.full_fn           = full_fn;
+       state->caller.full_private      = full_private;
+
+       if (initial_read_size == 0) {
+               tevent_req_error(req, EINVAL);
+               return tevent_req_post(req, ev);
+       }
+
+       buf = talloc_array(state, uint8_t, initial_read_size);
+       if (tevent_req_nomem(buf, req)) {
+               return tevent_req_post(req, ev);
+       }
+       state->pdu_blob.data = buf;
+       state->pdu_blob.length = initial_read_size;
+
+       state->tmp_vector.iov_base = buf;
+       state->tmp_vector.iov_len = initial_read_size;
+
+       subreq = tstream_readv_send(state, ev, stream, &state->tmp_vector, 1);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
+
+       return req;
+}
+
+static void tstream_read_pdu_blob_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq,
+               struct tevent_req);
+       struct tstream_read_pdu_blob_state *state =
+               tevent_req_data(req,
+               struct tstream_read_pdu_blob_state);
+       ssize_t ret;
+       int sys_errno;
+       size_t pdu_size;
+       NTSTATUS status;
+       uint8_t *buf;
+
+       ret = tstream_readv_recv(subreq, &sys_errno);
+       TALLOC_FREE(subreq);
+       if (ret == -1) {
+               status = map_nt_error_from_unix(sys_errno);
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       status = state->caller.full_fn(state->caller.full_private,
+                                      state->pdu_blob, &pdu_size);
+       if (NT_STATUS_IS_OK(status)) {
+               tevent_req_done(req);
+               return;
+       } else if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+               /* more to get */
+       } else if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, pdu_size);
+       if (tevent_req_nomem(buf, req)) {
+               return;
+       }
+       state->pdu_blob.data = buf;
+       state->pdu_blob.length = pdu_size;
+
+       state->tmp_vector.iov_base = buf + state->tmp_vector.iov_len;
+       state->tmp_vector.iov_len = pdu_size - state->tmp_vector.iov_len;
+
+       subreq = tstream_readv_send(state,
+                                   state->caller.ev,
+                                   state->caller.stream,
+                                   &state->tmp_vector,
+                                   1);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
+}
+
+NTSTATUS tstream_read_pdu_blob_recv(struct tevent_req *req,
+                                   TALLOC_CTX *mem_ctx,
+                                   DATA_BLOB *pdu_blob)
+{
+       struct tstream_read_pdu_blob_state *state = tevent_req_data(req,
+                                       struct tstream_read_pdu_blob_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               tevent_req_received(req);
+               return status;
+       }
+
+       *pdu_blob = state->pdu_blob;
+       talloc_steal(mem_ctx, pdu_blob->data);
+
+       tevent_req_received(req);
+       return NT_STATUS_OK;
+}
+
diff --git a/libcli/util/tstream.h b/libcli/util/tstream.h
new file mode 100644 (file)
index 0000000..a945287
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *
+ *  Copyright (C) Stefan Metzmacher 2009
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _LIBCLI_UTIL_TSTREAM_H_
+#define _LIBCLI_UTIL_TSTREAM_H_
+
+/**
+ * @brief A helper function to read a full PDU from a stream
+ *
+ * This function is designed for simple PDUs and as compat layer
+ * for the Samba4 packet interface.
+ *
+ * tstream_readv_pdu_send() is a more powerful interface,
+ * which is part of the main (non samba specific) tsocket code.
+ *
+ * @param[in] mem_ctx          The memory context for the result.
+ *
+ * @param[in] ev               The event context the operation should work on.
+ *
+ * @param[in] stream           The stream to read data from.
+ *
+ * @param[in] inital_read_size The initial byte count that is needed to workout
+ *                             the full pdu size.
+ *
+ * @param[in] full_fn          The callback function that will report the size
+ *                             of the full pdu.
+ *
+ * @param[in] full_private     The private data for the callback function.
+ *
+ * @return                     The async request handle. NULL on fatal error.
+ *
+ * @see tstream_read_pdu_blob_recv()
+ * @see tstream_readv_pdu_send()
+ * @see tstream_readv_pdu_queue_send()
+ *
+ */
+struct tevent_req *tstream_read_pdu_blob_send(TALLOC_CTX *mem_ctx,
+                               struct tevent_context *ev,
+                               struct tstream_context *stream,
+                               size_t inital_read_size,
+                               NTSTATUS (*full_fn)(void *private_data,
+                                                   DATA_BLOB blob,
+                                                   size_t *packet_size),
+                               void *full_private);
+/**
+ * @brief Receive the result of the tstream_read_pdu_blob_send() call.
+ *
+ * @param[in] req      The tevent request from tstream_read_pdu_blob_send().
+ *
+ * @param[in] mem_ctx  The memory context for returned pdu DATA_BLOB.
+ *
+ * @param[in] pdu_blob The DATA_BLOB with the full pdu.
+ *
+ * @return             The NTSTATUS result, NT_STATUS_OK on success
+ *                     and others on failure.
+ *
+ * @see tstream_read_pdu_blob_send()
+ */
+NTSTATUS tstream_read_pdu_blob_recv(struct tevent_req *req,
+                                   TALLOC_CTX *mem_ctx,
+                                   DATA_BLOB *pdu_blob);
+
+#endif /* _LIBCLI_UTIL_TSTREAM_H_ */
index 340cd2ae41822fa404681402ce396e8d50080215..f67250d4b067b3312090dee463520ab44f8d556b 100644 (file)
@@ -8,6 +8,11 @@ LIBSAMBA-ERRORS_OBJ_FILES = $(addprefix ../libcli/util/, doserr.o ) $(libclisrcd
 
 PUBLIC_HEADERS += $(addprefix ../libcli/util/, error.h ntstatus.h doserr.h werror.h)
 
+[SUBSYSTEM::LIBSAMBA_TSOCKET]
+PUBLIC_DEPENDENCIES = LIBTSOCKET UTIL_TEVENT
+
+LIBSAMBA_TSOCKET_OBJ_FILES = $(addprefix ../libcli/util/, tstream.o)
+
 [SUBSYSTEM::LIBCLI_LSA]
 PUBLIC_DEPENDENCIES = RPC_NDR_LSA
 PRIVATE_DEPENDENCIES = LIBSECURITY