ctdb-failover: Split statd_callout add-client/del-client
[Samba.git] / libcli / named_pipe_auth / tstream_u32_read.c
blobc8e95ef6b9986b72bd1e1a8659fdf5db32533fd8
1 /*
2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Volker Lendecke 2019
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/>.
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "tstream_u32_read.h"
23 #include "lib/util/byteorder.h"
24 #include "lib/util/tevent_unix.h"
26 struct tstream_u32_read_state {
27 size_t max_msglen;
28 size_t buflen;
29 uint8_t *buf;
32 static int tstream_u32_read_next_vector(struct tstream_context *stream,
33 void *private_data,
34 TALLOC_CTX *mem_ctx,
35 struct iovec **_vector,
36 size_t *_count);
37 static void tstream_u32_read_done(struct tevent_req *subreq);
39 struct tevent_req *tstream_u32_read_send(
40 TALLOC_CTX *mem_ctx,
41 struct tevent_context *ev,
42 uint32_t max_msglen,
43 struct tstream_context *stream)
45 struct tevent_req *req = NULL, *subreq = NULL;
46 struct tstream_u32_read_state *state = NULL;
48 req = tevent_req_create(
49 mem_ctx, &state, struct tstream_u32_read_state);
50 if (req == NULL) {
51 return NULL;
53 state->max_msglen = max_msglen;
55 subreq = tstream_readv_pdu_send(
56 state,
57 ev,
58 stream,
59 tstream_u32_read_next_vector,
60 state);
61 if (tevent_req_nomem(subreq, req)) {
62 return tevent_req_post(req, ev);
64 tevent_req_set_callback(subreq, tstream_u32_read_done, req);
65 return req;
68 static int tstream_u32_read_next_vector(struct tstream_context *stream,
69 void *private_data,
70 TALLOC_CTX *mem_ctx,
71 struct iovec **_vector,
72 size_t *_count)
74 struct tstream_u32_read_state *state = talloc_get_type_abort(
75 private_data, struct tstream_u32_read_state);
76 size_t buflen = talloc_get_size(state->buf);
77 struct iovec *vector;
78 uint32_t msg_len;
79 size_t ofs = 0;
80 size_t count;
82 if (buflen == 0) {
83 msg_len = 4;
84 state->buf = talloc_array(state, uint8_t, msg_len);
85 if (state->buf == NULL) {
86 return -1;
88 } else if (buflen == 4) {
90 ofs = 4;
92 msg_len = RIVAL(state->buf, 0);
93 if ((msg_len == 0) || (msg_len > state->max_msglen)) {
94 errno = EMSGSIZE;
95 return -1;
97 msg_len += ofs;
98 if (msg_len < ofs) {
99 errno = EMSGSIZE;
100 return -1;
103 state->buf = talloc_realloc(
104 state, state->buf, uint8_t, msg_len);
105 if (state->buf == NULL) {
106 return -1;
108 } else {
109 *_vector = NULL;
110 *_count = 0;
111 return 0;
114 vector = talloc(mem_ctx, struct iovec);
115 if (vector == NULL) {
116 return -1;
118 *vector = (struct iovec) {
119 .iov_base = state->buf + ofs, .iov_len = msg_len - ofs,
121 count = 1;
123 *_vector = vector;
124 *_count = count;
125 return 0;
128 static void tstream_u32_read_done(struct tevent_req *subreq)
130 struct tevent_req *req = tevent_req_callback_data(
131 subreq, struct tevent_req);
132 int ret, err;
134 ret = tstream_readv_pdu_recv(subreq, &err);
135 TALLOC_FREE(subreq);
136 if (ret == -1) {
137 tevent_req_error(req, err);
138 return;
140 tevent_req_done(req);
143 int tstream_u32_read_recv(
144 struct tevent_req *req,
145 TALLOC_CTX *mem_ctx,
146 uint8_t **buf,
147 size_t *buflen)
149 struct tstream_u32_read_state *state = tevent_req_data(
150 req, struct tstream_u32_read_state);
151 int err;
153 if (tevent_req_is_unix_error(req, &err)) {
154 return err;
156 *buflen = talloc_get_size(state->buf);
157 *buf = talloc_move(mem_ctx, &state->buf);
158 return 0;