947a27443d890b86a940af263d0d35d9cb7cf311
[amitay/samba.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/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                                     (const uint8 *)msg_all->buf, msg_all->len);
116
117         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
118
119                 /*
120                  * If the pid was not found delete the entry from
121                  * serverid.tdb
122                  */
123
124                 DEBUG(2, ("pid %s doesn't exist\n", procid_str_static(id)));
125
126                 dbwrap_record_delete(rec);
127         }
128         msg_all->n_sent++;
129         return 0;
130 }
131
132 /**
133  * Send a message to all smbd processes.
134  *
135  * It isn't very efficient, but should be OK for the sorts of
136  * applications that use it. When we need efficient broadcast we can add
137  * it.
138  *
139  * @param n_sent Set to the number of messages sent.  This should be
140  * equal to the number of processes, but be careful for races.
141  *
142  * @retval True for success.
143  **/
144 bool message_send_all(struct messaging_context *msg_ctx,
145                       int msg_type,
146                       const void *buf, size_t len,
147                       int *n_sent)
148 {
149         struct msg_all msg_all;
150
151         msg_all.msg_type = msg_type;
152         if (msg_type < 0x100) {
153                 msg_all.msg_flag = FLAG_MSG_GENERAL;
154         } else if (msg_type > 0x100 && msg_type < 0x200) {
155                 msg_all.msg_flag = FLAG_MSG_NMBD;
156         } else if (msg_type > 0x200 && msg_type < 0x300) {
157                 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
158         } else if (msg_type > 0x300 && msg_type < 0x400) {
159                 msg_all.msg_flag = FLAG_MSG_SMBD;
160         } else if (msg_type > 0x400 && msg_type < 0x600) {
161                 msg_all.msg_flag = FLAG_MSG_WINBIND;
162         } else if (msg_type > 4000 && msg_type < 5000) {
163                 msg_all.msg_flag = FLAG_MSG_DBWRAP;
164         } else {
165                 return false;
166         }
167
168         msg_all.buf = buf;
169         msg_all.len = len;
170         msg_all.n_sent = 0;
171         msg_all.msg_ctx = msg_ctx;
172
173         serverid_traverse(traverse_fn, &msg_all);
174         if (n_sent)
175                 *n_sent = msg_all.n_sent;
176         return true;
177 }
178
179 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 
180                                          struct event_context *ev)
181 {
182         struct messaging_context *ctx;
183         NTSTATUS status;
184
185         if (!(ctx = talloc_zero(mem_ctx, struct messaging_context))) {
186                 return NULL;
187         }
188
189         ctx->id = procid_self();
190         ctx->event_ctx = ev;
191
192         status = messaging_tdb_init(ctx, ctx, &ctx->local);
193
194         if (!NT_STATUS_IS_OK(status)) {
195                 DEBUG(2, ("messaging_tdb_init failed: %s\n",
196                           nt_errstr(status)));
197                 TALLOC_FREE(ctx);
198                 return NULL;
199         }
200
201 #ifdef CLUSTER_SUPPORT
202         if (lp_clustering()) {
203                 status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
204
205                 if (!NT_STATUS_IS_OK(status)) {
206                         DEBUG(2, ("messaging_ctdbd_init failed: %s\n",
207                                   nt_errstr(status)));
208                         TALLOC_FREE(ctx);
209                         return NULL;
210                 }
211         }
212         ctx->id.vnn = get_my_vnn();
213 #endif
214
215         messaging_register(ctx, NULL, MSG_PING, ping_message);
216
217         /* Register some debugging related messages */
218
219         register_msg_pool_usage(ctx);
220         register_dmalloc_msgs(ctx);
221         debug_register_msgs(ctx);
222
223         return ctx;
224 }
225
226 struct server_id messaging_server_id(const struct messaging_context *msg_ctx)
227 {
228         return msg_ctx->id;
229 }
230
231 /*
232  * re-init after a fork
233  */
234 NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
235 {
236         NTSTATUS status;
237
238         TALLOC_FREE(msg_ctx->local);
239
240         msg_ctx->id = procid_self();
241
242         status = messaging_tdb_init(msg_ctx, msg_ctx, &msg_ctx->local);
243         if (!NT_STATUS_IS_OK(status)) {
244                 DEBUG(0, ("messaging_tdb_init failed: %s\n",
245                           nt_errstr(status)));
246                 return status;
247         }
248
249 #ifdef CLUSTER_SUPPORT
250         TALLOC_FREE(msg_ctx->remote);
251
252         if (lp_clustering()) {
253                 status = messaging_ctdbd_init(msg_ctx, msg_ctx,
254                                               &msg_ctx->remote);
255
256                 if (!NT_STATUS_IS_OK(status)) {
257                         DEBUG(1, ("messaging_ctdbd_init failed: %s\n",
258                                   nt_errstr(status)));
259                         return status;
260                 }
261         }
262
263 #endif
264
265         return NT_STATUS_OK;
266 }
267
268
269 /*
270  * Register a dispatch function for a particular message type. Allow multiple
271  * registrants
272 */
273 NTSTATUS messaging_register(struct messaging_context *msg_ctx,
274                             void *private_data,
275                             uint32_t msg_type,
276                             void (*fn)(struct messaging_context *msg,
277                                        void *private_data, 
278                                        uint32_t msg_type, 
279                                        struct server_id server_id,
280                                        DATA_BLOB *data))
281 {
282         struct messaging_callback *cb;
283
284         DEBUG(5, ("Registering messaging pointer for type %u - "
285                   "private_data=%p\n",
286                   (unsigned)msg_type, private_data));
287
288         /*
289          * Only one callback per type
290          */
291
292         for (cb = msg_ctx->callbacks; cb != NULL; cb = cb->next) {
293                 /* we allow a second registration of the same message
294                    type if it has a different private pointer. This is
295                    needed in, for example, the internal notify code,
296                    which creates a new notify context for each tree
297                    connect, and expects to receive messages to each of
298                    them. */
299                 if (cb->msg_type == msg_type && private_data == cb->private_data) {
300                         DEBUG(5,("Overriding messaging pointer for type %u - private_data=%p\n",
301                                   (unsigned)msg_type, private_data));
302                         cb->fn = fn;
303                         cb->private_data = private_data;
304                         return NT_STATUS_OK;
305                 }
306         }
307
308         if (!(cb = talloc(msg_ctx, struct messaging_callback))) {
309                 return NT_STATUS_NO_MEMORY;
310         }
311
312         cb->msg_type = msg_type;
313         cb->fn = fn;
314         cb->private_data = private_data;
315
316         DLIST_ADD(msg_ctx->callbacks, cb);
317         return NT_STATUS_OK;
318 }
319
320 /*
321   De-register the function for a particular message type.
322 */
323 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
324                           void *private_data)
325 {
326         struct messaging_callback *cb, *next;
327
328         for (cb = ctx->callbacks; cb; cb = next) {
329                 next = cb->next;
330                 if ((cb->msg_type == msg_type)
331                     && (cb->private_data == private_data)) {
332                         DEBUG(5,("Deregistering messaging pointer for type %u - private_data=%p\n",
333                                   (unsigned)msg_type, private_data));
334                         DLIST_REMOVE(ctx->callbacks, cb);
335                         TALLOC_FREE(cb);
336                 }
337         }
338 }
339
340 /*
341   Send a message to a particular server
342 */
343 NTSTATUS messaging_send(struct messaging_context *msg_ctx,
344                         struct server_id server, uint32_t msg_type,
345                         const DATA_BLOB *data)
346 {
347 #ifdef CLUSTER_SUPPORT
348         if (!procid_is_local(&server)) {
349                 return msg_ctx->remote->send_fn(msg_ctx, server,
350                                                 msg_type, data,
351                                                 msg_ctx->remote);
352         }
353 #endif
354         return msg_ctx->local->send_fn(msg_ctx, server, msg_type, data,
355                                        msg_ctx->local);
356 }
357
358 NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
359                             struct server_id server, uint32_t msg_type,
360                             const uint8 *buf, size_t len)
361 {
362         DATA_BLOB blob = data_blob_const(buf, len);
363         return messaging_send(msg_ctx, server, msg_type, &blob);
364 }
365
366 /*
367   Dispatch one messaging_rec
368 */
369 void messaging_dispatch_rec(struct messaging_context *msg_ctx,
370                             struct messaging_rec *rec)
371 {
372         struct messaging_callback *cb, *next;
373
374         for (cb = msg_ctx->callbacks; cb != NULL; cb = next) {
375                 next = cb->next;
376                 if (cb->msg_type == rec->msg_type) {
377                         cb->fn(msg_ctx, cb->private_data, rec->msg_type,
378                                rec->src, &rec->buf);
379                         /* we continue looking for matching messages
380                            after finding one. This matters for
381                            subsystems like the internal notify code
382                            which register more than one handler for
383                            the same message type */
384                 }
385         }
386         return;
387 }
388
389 /** @} **/