ctdb-scripts: Don't set arp_filter=1 by default in 10.interface
[samba4-gss.git] / source4 / libcli / composite / composite.c
blob3598637b639bc31b6462721db3e3bbeb82c8eec6
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2005
5 Copyright (C) Andrew Tridgell 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 composite API helper functions
24 #include "includes.h"
25 #include "lib/events/events.h"
26 #include "libcli/smb2/smb2.h"
27 #include "libcli/composite/composite.h"
28 #include "../libcli/nbt/libnbt.h"
31 create a new composite_context structure
32 and initialize it
34 _PUBLIC_ struct composite_context *composite_create(TALLOC_CTX *mem_ctx,
35 struct tevent_context *ev)
37 struct composite_context *c;
39 c = talloc_zero(mem_ctx, struct composite_context);
40 if (!c) return NULL;
41 c->state = COMPOSITE_STATE_IN_PROGRESS;
42 c->event_ctx = ev;
44 return c;
48 block until a composite function has completed, then return the status
50 _PUBLIC_ NTSTATUS composite_wait(struct composite_context *c)
52 if (c == NULL) return NT_STATUS_NO_MEMORY;
54 c->used_wait = true;
56 while (c->state < COMPOSITE_STATE_DONE) {
57 if (tevent_loop_once(c->event_ctx) != 0) {
58 return NT_STATUS_UNSUCCESSFUL;
62 return c->status;
66 block until a composite function has completed, then return the status.
67 Free the composite context before returning
69 _PUBLIC_ NTSTATUS composite_wait_free(struct composite_context *c)
71 NTSTATUS status = composite_wait(c);
72 talloc_free(c);
73 return status;
76 /*
77 callback from composite_done() and composite_error()
79 this is used to allow for a composite function to complete without
80 going through any state transitions. When that happens the caller
81 has had no opportunity to fill in the async callback fields
82 (ctx->async.fn and ctx->async.private_data) which means the usual way of
83 dealing with composite functions doesn't work. To cope with this,
84 we trigger a timer event that will happen then the event loop is
85 re-entered. This gives the caller a chance to setup the callback,
86 and allows the caller to ignore the fact that the composite
87 function completed early
89 static void composite_trigger(struct tevent_context *ev, struct tevent_timer *te,
90 struct timeval t, void *ptr)
92 struct composite_context *c = talloc_get_type(ptr, struct composite_context);
93 if (c->async.fn) {
94 c->async.fn(c);
99 _PUBLIC_ void composite_error(struct composite_context *ctx, NTSTATUS status)
101 /* you are allowed to pass NT_STATUS_OK to composite_error(), in which
102 case it is equivalent to composite_done() */
103 if (NT_STATUS_IS_OK(status)) {
104 composite_done(ctx);
105 return;
107 if (!ctx->used_wait && !ctx->async.fn) {
108 tevent_add_timer(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
110 ctx->status = status;
111 ctx->state = COMPOSITE_STATE_ERROR;
112 if (ctx->async.fn != NULL) {
113 ctx->async.fn(ctx);
117 _PUBLIC_ bool composite_nomem(const void *p, struct composite_context *ctx)
119 if (p != NULL) {
120 return false;
122 composite_error(ctx, NT_STATUS_NO_MEMORY);
123 return true;
126 _PUBLIC_ bool composite_is_ok(struct composite_context *ctx)
128 if (NT_STATUS_IS_OK(ctx->status)) {
129 return true;
131 composite_error(ctx, ctx->status);
132 return false;
135 _PUBLIC_ void composite_done(struct composite_context *ctx)
137 if (!ctx->used_wait && !ctx->async.fn) {
138 tevent_add_timer(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
140 ctx->state = COMPOSITE_STATE_DONE;
141 if (ctx->async.fn != NULL) {
142 ctx->async.fn(ctx);
146 _PUBLIC_ void composite_continue(struct composite_context *ctx,
147 struct composite_context *new_ctx,
148 void (*continuation)(struct composite_context *),
149 void *private_data)
151 if (composite_nomem(new_ctx, ctx)) return;
152 new_ctx->async.fn = continuation;
153 new_ctx->async.private_data = private_data;
155 /* if we are setting up a continuation, and the context has
156 already finished, then we should run the callback with an
157 immediate event, otherwise we can be stuck forever */
158 if (new_ctx->state >= COMPOSITE_STATE_DONE && continuation) {
159 tevent_add_timer(new_ctx->event_ctx, new_ctx, timeval_zero(), composite_trigger, new_ctx);
163 _PUBLIC_ void composite_continue_smb(struct composite_context *ctx,
164 struct smbcli_request *new_req,
165 void (*continuation)(struct smbcli_request *),
166 void *private_data)
168 if (composite_nomem(new_req, ctx)) return;
169 if (new_req->state > SMBCLI_REQUEST_RECV) {
170 composite_error(ctx, new_req->status);
171 return;
173 new_req->async.fn = continuation;
174 new_req->async.private_data = private_data;
177 _PUBLIC_ void composite_continue_smb2(struct composite_context *ctx,
178 struct smb2_request *new_req,
179 void (*continuation)(struct smb2_request *),
180 void *private_data)
182 if (composite_nomem(new_req, ctx)) return;
183 if (new_req->state > SMB2_REQUEST_RECV) {
184 composite_error(ctx, new_req->status);
185 return;
187 new_req->async.fn = continuation;
188 new_req->async.private_data = private_data;
191 _PUBLIC_ void composite_continue_nbt(struct composite_context *ctx,
192 struct nbt_name_request *new_req,
193 void (*continuation)(struct nbt_name_request *),
194 void *private_data)
196 if (composite_nomem(new_req, ctx)) return;
197 new_req->async.fn = continuation;
198 new_req->async.private_data = private_data;