libcli/util: add tstream_read_pdu_blob_send/recv
authorStefan Metzmacher <metze@samba.org>
Wed, 4 Nov 2009 15:07:43 +0000 (16:07 +0100)
committerStefan Metzmacher <metze@samba.org>
Wed, 4 Nov 2009 15:16:09 +0000 (16:16 +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..9268196
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ *  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 <tsocket.h>
+#include <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_t)(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 inital_read_size,
+                               NTSTATUS (*full_fn_t)(void *private_data,
+                                                     DATA_BLOB blob,
+                                                     size_t *packet_size);
+                               void *full_fn_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 tdgram_read_pdu_blob_state *state = tevent_req_data(req,
+                                       struct tdgram_read_pdu_blob_state);
+       ssize_t ret;
+       int sys_errno;
+       size_t pdu_size;
+
+       ret = tstream_readv_recv(subreq, &sys_errno);
+       TALLOC_FREE(subreq);
+       if (ret == -1) {
+               status = map_nt_error_from_unix(sys_errno);
+               tevent_req_ntstatus(req, status);
+               return;
+       }
+
+       status = state->caller.full_fn(state->caller.full_private,
+                                      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_ntstatus(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);
+       int ret;
+
+       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..220a10d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  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/>.
+ */
+
+#ifdef _LIBCLI_UTIL_TSTREAM_H_
+#define _LIBCLI_UTIL_TSTREAM_H_
+
+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_t)(void *private_data,
+                                                     DATA_BLOB blob,
+                                                     size_t *packet_size);
+                               void *full_fn_private);
+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..f38c5365588c44714db373782a2c2ca6f21d0e61 100644 (file)
@@ -8,6 +8,10 @@ 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]
+
+LIBSAMBA_TSOCKET_OBJ_FILES = $(addprefix ../libcli/util/, tstream.o)
+
 [SUBSYSTEM::LIBCLI_LSA]
 PUBLIC_DEPENDENCIES = RPC_NDR_LSA
 PRIVATE_DEPENDENCIES = LIBSECURITY