4335554c2a0f6a9ef86a3f826f1ee4486ae25f54
[vlendec/samba-autobuild/.git] / source3 / lib / messages.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba internal messaging functions
4    Copyright (C) Andrew Tridgell 2000
5    Copyright (C) 2001 by Martin Pool
6    Copyright (C) 2002 by Jeremy Allison
7    Copyright (C) 2007 by Volker Lendecke
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /**
24   @defgroup messages Internal messaging framework
25   @{
26   @file messages.c
27   
28   @brief  Module for internal messaging between Samba daemons. 
29
30    The idea is that if a part of Samba wants to do communication with
31    another Samba process then it will do a message_register() of a
32    dispatch function, and use message_send_pid() to send messages to
33    that process.
34
35    The dispatch function is given the pid of the sender, and it can
36    use that to reply by message_send_pid().  See ping_message() for a
37    simple example.
38
39    @caution Dispatch functions must be able to cope with incoming
40    messages on an *odd* byte boundary.
41
42    This system doesn't have any inherent size limitations but is not
43    very efficient for large messages or when messages are sent in very
44    quick succession.
45
46 */
47
48 #include "includes.h"
49 #include "dbwrap.h"
50 #include "serverid.h"
51 #include "messages.h"
52
53 struct messaging_callback {
54         struct messaging_callback *prev, *next;
55         uint32 msg_type;
56         void (*fn)(struct messaging_context *msg, void *private_data, 
57                    uint32_t msg_type, 
58                    struct server_id server_id, DATA_BLOB *data);
59         void *private_data;
60 };
61
62 /****************************************************************************
63  A useful function for testing the message system.
64 ****************************************************************************/
65
66 static void ping_message(struct messaging_context *msg_ctx,
67                          void *private_data,
68                          uint32_t msg_type,
69                          struct server_id src,
70                          DATA_BLOB *data)
71 {
72         const char *msg = data->data ? (const char *)data->data : "none";
73
74         DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
75                  procid_str_static(&src), msg));
76         messaging_send(msg_ctx, src, MSG_PONG, data);
77 }
78
79 /****************************************************************************
80  Register/replace a dispatch function for a particular message type.
81  JRA changed Dec 13 2006. Only one message handler now permitted per type.
82  *NOTE*: Dispatch functions must be able to cope with incoming
83  messages on an *odd* byte boundary.
84 ****************************************************************************/
85
86 struct msg_all {
87         struct messaging_context *msg_ctx;
88         int msg_type;
89         uint32 msg_flag;
90         const void *buf;
91         size_t len;
92         int n_sent;
93 };
94
95 /****************************************************************************
96  Send one of the messages for the broadcast.
97 ****************************************************************************/
98
99 static int traverse_fn(struct db_record *rec, const struct server_id *id,
100                        uint32_t msg_flags, void *state)
101 {
102         struct msg_all *msg_all = (struct msg_all *)state;
103         NTSTATUS status;
104
105         /* Don't send if the receiver hasn't registered an interest. */
106
107         if((msg_flags & msg_all->msg_flag) == 0) {
108                 return 0;
109         }
110
111         /* If the msg send fails because the pid was not found (i.e. smbd died), 
112          * the msg has already been deleted from the messages.tdb.*/
113
114         status = messaging_send_buf(msg_all->msg_ctx, *id, msg_all->msg_type,
115                                     (uint8 *)msg_all->buf, msg_all->len);
116
117         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
118                 
119                 /* If the pid was not found delete the entry from connections.tdb */
120
121                 DEBUG(2, ("pid %s doesn't exist\n", procid_str_static(id)));
122
123                 rec->delete_rec(rec);
124         }
125         msg_all->n_sent++;
126         return 0;
127 }
128
129 /**
130  * Send a message to all smbd processes.
131  *
132  * It isn't very efficient, but should be OK for the sorts of
133  * applications that use it. When we need efficient broadcast we can add
134  * it.
135  *
136  * @param n_sent Set to the number of messages sent.  This should be
137  * equal to the number of processes, but be careful for races.
138  *
139  * @retval True for success.
140  **/
141 bool message_send_all(struct messaging_context *msg_ctx,
142                       int msg_type,
143                       const void *buf, size_t len,
144                       int *n_sent)
145 {
146         struct msg_all msg_all;
147
148         msg_all.msg_type = msg_type;
149         if (msg_type < 1000)
150                 msg_all.msg_flag = FLAG_MSG_GENERAL;
151         else if (msg_type > 1000 && msg_type < 2000)
152                 msg_all.msg_flag = FLAG_MSG_NMBD;
153         else if (msg_type > 2000 && msg_type < 2100)
154                 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
155         else if (msg_type > 2100 && msg_type < 3000)
156                 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
157         else if (msg_type > 3000 && msg_type < 4000)
158                 msg_all.msg_flag = FLAG_MSG_SMBD;
159         else if (msg_type > 4000 && msg_type < 5000)
160                 msg_all.msg_flag = FLAG_MSG_DBWRAP;
161         else
162                 return False;
163
164         msg_all.buf = buf;
165         msg_all.len = len;
166         msg_all.n_sent = 0;
167         msg_all.msg_ctx = msg_ctx;
168
169         serverid_traverse(traverse_fn, &msg_all);
170         if (n_sent)
171                 *n_sent = msg_all.n_sent;
172         return True;
173 }
174
175 struct event_context *messaging_event_context(struct messaging_context *msg_ctx)
176 {
177         return msg_ctx->event_ctx;
178 }
179
180 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 
181                                          struct server_id server_id, 
182                                          struct event_context *ev)
183 {
184         struct messaging_context *ctx;
185         NTSTATUS status;
186
187         if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
188                 return NULL;
189         }
190
191         ctx->id = server_id;
192         ctx->event_ctx = ev;
193
194         status = messaging_tdb_init(ctx, ctx, &ctx->local);
195
196         if (!NT_STATUS_IS_OK(status)) {
197                 DEBUG(2, ("messaging_tdb_init failed: %s\n",
198                           nt_errstr(status)));
199                 TALLOC_FREE(ctx);
200                 return NULL;
201         }
202
203 #ifdef CLUSTER_SUPPORT
204         if (lp_clustering()) {
205                 status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
206
207                 if (!NT_STATUS_IS_OK(status)) {
208                         DEBUG(2, ("messaging_ctdb_init failed: %s\n",
209                                   nt_errstr(status)));
210                         TALLOC_FREE(ctx);
211                         return NULL;
212                 }
213         }
214         ctx->id.vnn = get_my_vnn();
215 #endif
216
217         messaging_register(ctx, NULL, MSG_PING, ping_message);
218
219         /* Register some debugging related messages */
220
221         register_msg_pool_usage(ctx);
222         register_dmalloc_msgs(ctx);
223         debug_register_msgs(ctx);
224
225         return ctx;
226 }
227
228 struct server_id messaging_server_id(const struct messaging_context *msg_ctx)
229 {
230         return msg_ctx->id;
231 }
232
233 /*
234  * re-init after a fork
235  */
236 NTSTATUS messaging_reinit(struct messaging_context *msg_ctx,
237                           struct server_id id)
238 {
239         NTSTATUS status;
240
241         TALLOC_FREE(msg_ctx->local);
242
243         msg_ctx->id = id;
244
245         status = messaging_tdb_init(msg_ctx, msg_ctx, &msg_ctx->local);
246         if (!NT_STATUS_IS_OK(status)) {
247                 DEBUG(0, ("messaging_tdb_init failed: %s\n",
248                           nt_errstr(status)));
249                 return status;
250         }
251
252 #ifdef CLUSTER_SUPPORT
253         TALLOC_FREE(msg_ctx->remote);
254
255         if (lp_clustering()) {
256                 status = messaging_ctdbd_init(msg_ctx, msg_ctx,
257                                               &msg_ctx->remote);
258
259                 if (!NT_STATUS_IS_OK(status)) {
260                         DEBUG(1, ("messaging_ctdb_init failed: %s\n",
261                                   nt_errstr(status)));
262                         return status;
263                 }
264         }
265
266 #endif
267
268         return NT_STATUS_OK;
269 }
270
271
272 /*
273  * Register a dispatch function for a particular message type. Allow multiple
274  * registrants
275 */
276 NTSTATUS messaging_register(struct messaging_context *msg_ctx,
277                             void *private_data,
278                             uint32_t msg_type,
279                             void (*fn)(struct messaging_context *msg,
280                                        void *private_data, 
281                                        uint32_t msg_type, 
282                                        struct server_id server_id,
283                                        DATA_BLOB *data))
284 {
285         struct messaging_callback *cb;
286
287         /*
288          * Only one callback per type
289          */
290
291         for (cb = msg_ctx->callbacks; cb != NULL; cb = cb->next) {
292                 /* we allow a second registration of the same message
293                    type if it has a different private pointer. This is
294                    needed in, for example, the internal notify code,
295                    which creates a new notify context for each tree
296                    connect, and expects to receive messages to each of
297                    them. */
298                 if (cb->msg_type == msg_type && private_data == cb->private_data) {
299                         DEBUG(5,("Overriding messaging pointer for type %u - private_data=%p\n",
300                                   (unsigned)msg_type, private_data));
301                         cb->fn = fn;
302                         cb->private_data = private_data;
303                         return NT_STATUS_OK;
304                 }
305         }
306
307         if (!(cb = talloc(msg_ctx, struct messaging_callback))) {
308                 return NT_STATUS_NO_MEMORY;
309         }
310
311         cb->msg_type = msg_type;
312         cb->fn = fn;
313         cb->private_data = private_data;
314
315         DLIST_ADD(msg_ctx->callbacks, cb);
316         return NT_STATUS_OK;
317 }
318
319 /*
320   De-register the function for a particular message type.
321 */
322 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
323                           void *private_data)
324 {
325         struct messaging_callback *cb, *next;
326
327         for (cb = ctx->callbacks; cb; cb = next) {
328                 next = cb->next;
329                 if ((cb->msg_type == msg_type)
330                     && (cb->private_data == private_data)) {
331                         DEBUG(5,("Deregistering messaging pointer for type %u - private_data=%p\n",
332                                   (unsigned)msg_type, private_data));
333                         DLIST_REMOVE(ctx->callbacks, cb);
334                         TALLOC_FREE(cb);
335                 }
336         }
337 }
338
339 /*
340   Send a message to a particular server
341 */
342 NTSTATUS messaging_send(struct messaging_context *msg_ctx,
343                         struct server_id server, uint32_t msg_type,
344                         const DATA_BLOB *data)
345 {
346 #ifdef CLUSTER_SUPPORT
347         if (!procid_is_local(&server)) {
348                 return msg_ctx->remote->send_fn(msg_ctx, server,
349                                                 msg_type, data,
350                                                 msg_ctx->remote);
351         }
352 #endif
353         return msg_ctx->local->send_fn(msg_ctx, server, msg_type, data,
354                                        msg_ctx->local);
355 }
356
357 NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
358                             struct server_id server, uint32_t msg_type,
359                             const uint8 *buf, size_t len)
360 {
361         DATA_BLOB blob = data_blob_const(buf, len);
362         return messaging_send(msg_ctx, server, msg_type, &blob);
363 }
364
365 /*
366   Dispatch one messaging_rec
367 */
368 void messaging_dispatch_rec(struct messaging_context *msg_ctx,
369                             struct messaging_rec *rec)
370 {
371         struct messaging_callback *cb, *next;
372
373         for (cb = msg_ctx->callbacks; cb != NULL; cb = next) {
374                 next = cb->next;
375                 if (cb->msg_type == rec->msg_type) {
376                         cb->fn(msg_ctx, cb->private_data, rec->msg_type,
377                                rec->src, &rec->buf);
378                         /* we continue looking for matching messages
379                            after finding one. This matters for
380                            subsystems like the internal notify code
381                            which register more than one handler for
382                            the same message type */
383                 }
384         }
385         return;
386 }
387
388 /** @} **/