ctdb-scripts: Update statd-callout to try several configuration files
[vlendec/samba-autobuild/.git] / ctdb / event / event_request.c
1 /*
2    CTDB event daemon - handle requests
3
4    Copyright (C) Amitay Isaacs  2018
5
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.
10
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.
15
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/>.
18 */
19
20 #include "replace.h"
21
22 #include "lib/util/debug.h"
23 #include "lib/util/tevent_unix.h"
24
25 #include "common/logging.h"
26
27 #include "event/event_private.h"
28 #include "event/event_protocol_api.h"
29
30 struct event_request_state {
31         struct ctdb_event_request *request;
32         struct ctdb_event_reply *reply;
33 };
34
35 static void event_request_done(struct tevent_req *subreq);
36
37 static struct tevent_req *event_request_send(
38                                         TALLOC_CTX *mem_ctx,
39                                         struct tevent_context *ev,
40                                         struct event_context *eventd,
41                                         struct ctdb_event_header *header,
42                                         struct ctdb_event_request *request)
43 {
44         struct tevent_req *req, *subreq;
45         struct event_request_state *state;
46
47         req = tevent_req_create(mem_ctx, &state, struct event_request_state);
48         if (req == NULL) {
49                 return NULL;
50         }
51
52         state->request = request;
53
54         subreq = event_cmd_dispatch_send(state, ev, eventd, request);
55         if (tevent_req_nomem(subreq, req)) {
56                 return tevent_req_post(req, ev);
57         }
58         tevent_req_set_callback(subreq, event_request_done, req);
59
60         return req;
61 }
62
63 static void event_request_done(struct tevent_req *subreq)
64 {
65         struct tevent_req *req = tevent_req_callback_data(
66                 subreq, struct tevent_req);
67         struct event_request_state *state = tevent_req_data(
68                 req, struct event_request_state);
69         int ret;
70         bool ok;
71
72         ok = event_cmd_dispatch_recv(subreq, &ret, state, &state->reply);
73         TALLOC_FREE(subreq);
74         if (!ok) {
75                 D_ERR("Command %s failed, ret=%d\n",
76                       ctdb_event_command_to_string(state->request->cmd), ret);
77
78                 state->reply = talloc_zero(state, struct ctdb_event_reply);
79                 if (tevent_req_nomem(state->reply, req)) {
80                         return;
81                 }
82
83                 state->reply->cmd = state->request->cmd;
84                 state->reply->result = EIO;
85         }
86
87         tevent_req_done(req);
88 }
89
90 static bool event_request_recv(struct tevent_req *req,
91                                int *perr,
92                                TALLOC_CTX *mem_ctx,
93                                struct ctdb_event_reply **reply)
94 {
95         struct event_request_state *state = tevent_req_data(
96                 req, struct event_request_state);
97
98         if (tevent_req_is_unix_error(req, perr)) {
99                 return false;
100         }
101
102         *reply = talloc_steal(mem_ctx, state->reply);
103
104         return true;
105 }
106
107 struct event_pkt_state {
108         struct ctdb_event_header header;
109         struct ctdb_event_request *request;
110         uint8_t *buf;
111         size_t buflen;
112 };
113
114 static void event_pkt_done(struct tevent_req *subreq);
115
116 struct tevent_req *event_pkt_send(TALLOC_CTX *mem_ctx,
117                                   struct tevent_context *ev,
118                                   struct event_context *eventd,
119                                   uint8_t *buf,
120                                   size_t buflen)
121 {
122         struct tevent_req *req, *subreq;
123         struct event_pkt_state *state;
124         int ret;
125
126         req = tevent_req_create(mem_ctx, &state, struct event_pkt_state);
127         if (req == NULL) {
128                 return NULL;
129         }
130
131         ret = ctdb_event_request_pull(buf,
132                                       buflen,
133                                       &state->header,
134                                       state,
135                                       &state->request);
136         if (ret != 0) {
137                 /* Ignore invalid packets */
138                 D_ERR("Invalid packet received, buflen=%zu\n", buflen);
139                 tevent_req_error(req, EPROTO);
140                 return tevent_req_post(req, ev);
141         }
142
143         subreq = event_request_send(state,
144                                   ev,
145                                   eventd,
146                                   &state->header,
147                                   state->request);
148         if (tevent_req_nomem(subreq, req)) {
149                 return tevent_req_post(req, ev);
150         }
151         tevent_req_set_callback(subreq, event_pkt_done, req);
152
153         return req;
154 }
155
156 static void event_pkt_done(struct tevent_req *subreq)
157 {
158         struct tevent_req *req = tevent_req_callback_data(
159                 subreq, struct tevent_req);
160         struct event_pkt_state *state = tevent_req_data(
161                 req, struct event_pkt_state);
162         struct ctdb_event_header header;
163         struct ctdb_event_reply *reply;
164         int ret;
165         bool ok;
166
167         ok = event_request_recv(subreq, &ret, state, &reply);
168         TALLOC_FREE(subreq);
169         TALLOC_FREE(state->request);
170         if (!ok) {
171                 tevent_req_error(req, ret);
172                 return;
173         }
174
175         header = (struct ctdb_event_header) {
176                 .reqid = state->header.reqid,
177         };
178
179         state->buflen = ctdb_event_reply_len(&header, reply);
180         state->buf = talloc_zero_size(state, state->buflen);
181         if (tevent_req_nomem(state->buf, req)) {
182                 talloc_free(reply);
183                 return;
184         }
185
186         ret = ctdb_event_reply_push(&header,
187                                     reply,
188                                     state->buf,
189                                     &state->buflen);
190         talloc_free(reply);
191         if (ret != 0) {
192                 talloc_free(state->buf);
193                 tevent_req_error(req, ret);
194                 return;
195         }
196
197         tevent_req_done(req);
198 }
199
200 bool event_pkt_recv(struct tevent_req *req,
201                     int *perr,
202                     TALLOC_CTX *mem_ctx,
203                     uint8_t **buf,
204                     size_t *buflen)
205 {
206         struct event_pkt_state *state = tevent_req_data(
207                 req, struct event_pkt_state);
208
209         if (tevent_req_is_unix_error(req, perr)) {
210                 return false;
211         }
212
213         *buf = talloc_steal(mem_ctx, state->buf);
214         *buflen = state->buflen;
215
216         return true;
217 }