1bf2cf868580a4c9ea46c7bfd754fceb954385ed
[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 "librpc/gen_ndr/messaging.h"
50 #include "librpc/gen_ndr/ndr_messaging.h"
51 #include "dbwrap.h"
52 #include "serverid.h"
53
54 struct messaging_callback {
55         struct messaging_callback *prev, *next;
56         uint32 msg_type;
57         void (*fn)(struct messaging_context *msg, void *private_data, 
58                    uint32_t msg_type, 
59                    struct server_id server_id, DATA_BLOB *data);
60         void *private_data;
61 };
62
63 /****************************************************************************
64  A useful function for testing the message system.
65 ****************************************************************************/
66
67 static void ping_message(struct messaging_context *msg_ctx,
68                          void *private_data,
69                          uint32_t msg_type,
70                          struct server_id src,
71                          DATA_BLOB *data)
72 {
73         const char *msg = data->data ? (const char *)data->data : "none";
74
75         DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
76                  procid_str_static(&src), msg));
77         messaging_send(msg_ctx, src, MSG_PONG, data);
78 }
79
80 /****************************************************************************
81  Register/replace a dispatch function for a particular message type.
82  JRA changed Dec 13 2006. Only one message handler now permitted per type.
83  *NOTE*: Dispatch functions must be able to cope with incoming
84  messages on an *odd* byte boundary.
85 ****************************************************************************/
86
87 struct msg_all {
88         struct messaging_context *msg_ctx;
89         int msg_type;
90         uint32 msg_flag;
91         const void *buf;
92         size_t len;
93         int n_sent;
94 };
95
96 /****************************************************************************
97  Send one of the messages for the broadcast.
98 ****************************************************************************/
99
100 static int traverse_fn(struct db_record *rec, const struct server_id *id,
101                        uint32_t msg_flags, void *state)
102 {
103         struct msg_all *msg_all = (struct msg_all *)state;
104         NTSTATUS status;
105
106         /* Don't send if the receiver hasn't registered an interest. */
107
108         if((msg_flags & msg_all->msg_flag) == 0) {
109                 return 0;
110         }
111
112         /* If the msg send fails because the pid was not found (i.e. smbd died), 
113          * the msg has already been deleted from the messages.tdb.*/
114
115         status = messaging_send_buf(msg_all->msg_ctx, *id, msg_all->msg_type,
116                                     (uint8 *)msg_all->buf, msg_all->len);
117
118         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
119                 
120                 /* If the pid was not found delete the entry from connections.tdb */
121
122                 DEBUG(2, ("pid %s doesn't exist\n", procid_str_static(id)));
123
124                 rec->delete_rec(rec);
125         }
126         msg_all->n_sent++;
127         return 0;
128 }
129
130 /**
131  * Send a message to all smbd processes.
132  *
133  * It isn't very efficient, but should be OK for the sorts of
134  * applications that use it. When we need efficient broadcast we can add
135  * it.
136  *
137  * @param n_sent Set to the number of messages sent.  This should be
138  * equal to the number of processes, but be careful for races.
139  *
140  * @retval True for success.
141  **/
142 bool message_send_all(struct messaging_context *msg_ctx,
143                       int msg_type,
144                       const void *buf, size_t len,
145                       int *n_sent)
146 {
147         struct msg_all msg_all;
148
149         msg_all.msg_type = msg_type;
150         if (msg_type < 1000)
151                 msg_all.msg_flag = FLAG_MSG_GENERAL;
152         else if (msg_type > 1000 && msg_type < 2000)
153                 msg_all.msg_flag = FLAG_MSG_NMBD;
154         else if (msg_type > 2000 && msg_type < 2100)
155                 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
156         else if (msg_type > 2100 && msg_type < 3000)
157                 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
158         else if (msg_type > 3000 && msg_type < 4000)
159                 msg_all.msg_flag = FLAG_MSG_SMBD;
160         else if (msg_type > 4000 && msg_type < 5000)
161                 msg_all.msg_flag = FLAG_MSG_DBWRAP;
162         else
163                 return False;
164
165         msg_all.buf = buf;
166         msg_all.len = len;
167         msg_all.n_sent = 0;
168         msg_all.msg_ctx = msg_ctx;
169
170         serverid_traverse(traverse_fn, &msg_all);
171         if (n_sent)
172                 *n_sent = msg_all.n_sent;
173         return True;
174 }
175
176 struct event_context *messaging_event_context(struct messaging_context *msg_ctx)
177 {
178         return msg_ctx->event_ctx;
179 }
180
181 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 
182                                          struct server_id server_id, 
183                                          struct event_context *ev)
184 {
185         struct messaging_context *ctx;
186         NTSTATUS status;
187
188         if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
189                 return NULL;
190         }
191
192         ctx->id = server_id;
193         ctx->event_ctx = ev;
194
195         status = messaging_tdb_init(ctx, ctx, &ctx->local);
196
197         if (!NT_STATUS_IS_OK(status)) {
198                 DEBUG(2, ("messaging_tdb_init failed: %s\n",
199                           nt_errstr(status)));
200                 TALLOC_FREE(ctx);
201                 return NULL;
202         }
203
204 #ifdef CLUSTER_SUPPORT
205         if (lp_clustering()) {
206                 status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
207
208                 if (!NT_STATUS_IS_OK(status)) {
209                         DEBUG(2, ("messaging_ctdb_init failed: %s\n",
210                                   nt_errstr(status)));
211                         TALLOC_FREE(ctx);
212                         return NULL;
213                 }
214         }
215         ctx->id.vnn = get_my_vnn();
216 #endif
217
218         messaging_register(ctx, NULL, MSG_PING, ping_message);
219
220         /* Register some debugging related messages */
221
222         register_msg_pool_usage(ctx);
223         register_dmalloc_msgs(ctx);
224         debug_register_msgs(ctx);
225
226         return ctx;
227 }
228
229 struct server_id messaging_server_id(const struct messaging_context *msg_ctx)
230 {
231         return msg_ctx->id;
232 }
233
234 /*
235  * re-init after a fork
236  */
237 NTSTATUS messaging_reinit(struct messaging_context *msg_ctx,
238                           struct server_id id)
239 {
240         NTSTATUS status;
241
242         TALLOC_FREE(msg_ctx->local);
243
244         msg_ctx->id = id;
245
246         status = messaging_tdb_init(msg_ctx, msg_ctx, &msg_ctx->local);
247         if (!NT_STATUS_IS_OK(status)) {
248                 DEBUG(0, ("messaging_tdb_init failed: %s\n",
249                           nt_errstr(status)));
250                 return status;
251         }
252
253 #ifdef CLUSTER_SUPPORT
254         TALLOC_FREE(msg_ctx->remote);
255
256         if (lp_clustering()) {
257                 status = messaging_ctdbd_init(msg_ctx, msg_ctx,
258                                               &msg_ctx->remote);
259
260                 if (!NT_STATUS_IS_OK(status)) {
261                         DEBUG(1, ("messaging_ctdb_init failed: %s\n",
262                                   nt_errstr(status)));
263                         return status;
264                 }
265         }
266
267 #endif
268
269         return NT_STATUS_OK;
270 }
271
272
273 /*
274  * Register a dispatch function for a particular message type. Allow multiple
275  * registrants
276 */
277 NTSTATUS messaging_register(struct messaging_context *msg_ctx,
278                             void *private_data,
279                             uint32_t msg_type,
280                             void (*fn)(struct messaging_context *msg,
281                                        void *private_data, 
282                                        uint32_t msg_type, 
283                                        struct server_id server_id,
284                                        DATA_BLOB *data))
285 {
286         struct messaging_callback *cb;
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 /** @} **/