2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Stefan Metzmacher 2009
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include <tevent_ntstatus.h>
25 struct tstream_read_pdu_blob_state {
26 /* this structs are owned by the caller */
28 struct tevent_context *ev;
29 struct tstream_context *stream;
30 NTSTATUS (*full_fn_t)(void *private_data,
37 struct iovec tmp_vector;
40 static void tstream_read_pdu_blob_done(struct tevent_req *subreq);
42 struct tevent_req *tstream_read_pdu_blob_send(TALLOC_CTX *mem_ctx,
43 struct tevent_context *ev,
44 struct tstream_context *stream,
45 size_t inital_read_size,
46 NTSTATUS (*full_fn_t)(void *private_data,
49 void *full_fn_private)
51 struct tevent_req *req;
52 struct tstream_read_pdu_blob_state *state;
53 struct tevent_req *subreq;
56 req = tevent_req_create(mem_ctx, &state,
57 struct tstream_read_pdu_blob_state);
62 state->caller.ev = ev;
63 state->caller.stream = stream;
64 state->caller.full_fn = full_fn;
65 state->caller.full_private = full_private;
67 if (initial_read_size == 0) {
68 tevent_req_error(req, EINVAL);
69 return tevent_req_post(req, ev);
72 buf = talloc_array(state, uint8_t, initial_read_size);
73 if (tevent_req_nomem(buf, req)) {
74 return tevent_req_post(req, ev);
76 state->pdu_blob.data = buf;
77 state->pdu_blob.length = initial_read_size;
79 state->tmp_vector.iov_base = buf;
80 state->tmp_vector.iov_len = initial_read_size;
82 subreq = tstream_readv_send(state, ev, stream, &state->tmp_vector, 1);
83 if (tevent_req_nomem(subreq, req)) {
84 return tevent_req_post(req, ev);
86 tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
91 static void tstream_read_pdu_blob_done(struct tevent_req *subreq)
93 struct tevent_req *req = tevent_req_callback_data(subreq,
95 struct tdgram_read_pdu_blob_state *state = tevent_req_data(req,
96 struct tdgram_read_pdu_blob_state);
101 ret = tstream_readv_recv(subreq, &sys_errno);
104 status = map_nt_error_from_unix(sys_errno);
105 tevent_req_ntstatus(req, status);
109 status = state->caller.full_fn(state->caller.full_private,
110 pdu_blob, &pdu_size);
111 if (NT_STATUS_IS_OK(status)) {
112 tevent_req_done(req);
114 } else if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
116 } else if (!NT_STATUS_IS_OK(status)) {
117 tevent_req_ntstatus(req, status);
121 buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, pdu_size);
122 if (tevent_req_nomem(buf, req)) {
125 state->pdu_blob.data = buf;
126 state->pdu_blob.length = pdu_size;
128 state->tmp_vector.iov_base = buf + state->tmp_vector.iov_len;
129 state->tmp_vector.iov_len = pdu_size - state->tmp_vector.iov_len;
131 subreq = tstream_readv_send(state,
133 state->caller.stream,
136 if (tevent_req_nomem(subreq, req)) {
139 tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
142 NTSTATUS tstream_read_pdu_blob_recv(struct tevent_req *req,
146 struct tstream_read_pdu_blob_state *state = tevent_req_data(req,
147 struct tstream_read_pdu_blob_state);
150 if (tevent_req_is_nterror(req, &status)) {
151 tevent_req_received(req);
155 *pdu_blob = state->pdu_blob;
156 talloc_steal(mem_ctx, pdu_blob->data);
158 tevent_req_received(req);