s3:winbind: Add async wb_seqnums
[ira/wip.git] / source3 / winbindd / wb_seqnums.c
1 /*
2    Unix SMB/CIFS implementation.
3    async seqnums
4    Copyright (C) Volker Lendecke 2009
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 "includes.h"
21 #include "winbindd.h"
22 #include "librpc/gen_ndr/cli_wbint.h"
23
24 struct wb_seqnums_state {
25         int num_domains;
26         int num_received;
27
28         struct tevent_req **subreqs;
29         struct winbindd_domain **domains;
30         NTSTATUS *stati;
31         uint32_t *seqnums;
32 };
33
34 static void wb_seqnums_done(struct tevent_req *subreq);
35
36 struct tevent_req *wb_seqnums_send(TALLOC_CTX *mem_ctx,
37                                    struct tevent_context *ev)
38 {
39         struct tevent_req *req;
40         struct wb_seqnums_state *state;
41         struct winbindd_domain *domain;
42         int i;
43
44         req = tevent_req_create(mem_ctx, &state, struct wb_seqnums_state);
45         if (req == NULL) {
46                 return NULL;
47         }
48         state->num_received = 0;
49         state->num_domains = 0;
50
51         for (domain = domain_list(); domain != NULL; domain = domain->next) {
52                 state->num_domains += 1;
53         }
54
55         state->subreqs = talloc_array(state, struct tevent_req *,
56                                       state->num_domains);
57         state->domains = talloc_array(state, struct winbindd_domain *,
58                                       state->num_domains);
59         state->stati = talloc_array(state, NTSTATUS, state->num_domains);
60         state->seqnums = talloc_array(state, uint32_t, state->num_domains);
61
62         if ((state->subreqs == NULL) || (state->domains == NULL) ||
63             (state->stati == NULL) || (state->seqnums == NULL)) {
64                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
65                 return tevent_req_post(req, ev);
66         }
67
68         i = 0;
69
70         for (domain = domain_list(); domain != NULL; domain = domain->next) {
71                 state->domains[i] = domain;
72                 state->subreqs[i] = wb_seqnum_send(state->subreqs, ev, domain);
73                 if (tevent_req_nomem(state->subreqs[i], req)) {
74                         /* Don't even start all the other requests */
75                         TALLOC_FREE(state->subreqs);
76                         return tevent_req_post(req, ev);
77                 }
78                 tevent_req_set_callback(state->subreqs[i], wb_seqnums_done,
79                                         req);
80                 i += 1;
81         }
82         return req;
83 }
84
85 static void wb_seqnums_done(struct tevent_req *subreq)
86 {
87         struct tevent_req *req = tevent_req_callback_data(
88                 subreq, struct tevent_req);
89         struct wb_seqnums_state *state = tevent_req_data(
90                 req, struct wb_seqnums_state);
91         NTSTATUS status;
92         uint32_t seqnum;
93         int i;
94
95         status = wb_seqnum_recv(subreq, &seqnum);
96
97         for (i=0; i<state->num_domains; i++) {
98                 if (subreq == state->subreqs[i]) {
99                         state->subreqs[i] = NULL;
100                         state->stati[i] = status;
101                         if (NT_STATUS_IS_OK(status)) {
102                                 state->seqnums[i] = seqnum;
103                                 state->domains[i]->sequence_number = seqnum;
104                         }
105                         break;
106                 }
107         }
108         TALLOC_FREE(subreq);
109
110         state->num_received += 1;
111
112         if (state->num_received >= state->num_domains) {
113                 tevent_req_done(req);
114         }
115 }
116
117 NTSTATUS wb_seqnums_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
118                          int *num_domains, struct winbindd_domain ***domains,
119                          NTSTATUS **stati, uint32_t **seqnums)
120 {
121         struct wb_seqnums_state *state = tevent_req_data(
122                 req, struct wb_seqnums_state);
123         NTSTATUS status;
124
125         if (tevent_req_is_nterror(req, &status)) {
126                 return status;
127         }
128         *num_domains = state->num_domains;
129         *domains = talloc_move(mem_ctx, &state->domains);
130         *stati = talloc_move(mem_ctx, &state->stati);
131         *seqnums = talloc_move(mem_ctx, &state->seqnums);
132         return NT_STATUS_OK;
133 }