r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[kai/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
52 struct messaging_callback {
53         struct messaging_callback *prev, *next;
54         uint32 msg_type;
55         void (*fn)(struct messaging_context *msg, void *private_data, 
56                    uint32_t msg_type, 
57                    struct server_id server_id, DATA_BLOB *data);
58         void *private_data;
59 };
60
61 /****************************************************************************
62  A useful function for testing the message system.
63 ****************************************************************************/
64
65 static void ping_message(struct messaging_context *msg_ctx,
66                          void *private_data,
67                          uint32_t msg_type,
68                          struct server_id src,
69                          DATA_BLOB *data)
70 {
71         const char *msg = data->data ? (const char *)data->data : "none";
72
73         DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
74                  procid_str_static(&src), msg));
75         messaging_send(msg_ctx, src, MSG_PONG, data);
76 }
77
78 /****************************************************************************
79  Register/replace a dispatch function for a particular message type.
80  JRA changed Dec 13 2006. Only one message handler now permitted per type.
81  *NOTE*: Dispatch functions must be able to cope with incoming
82  messages on an *odd* byte boundary.
83 ****************************************************************************/
84
85 struct msg_all {
86         struct messaging_context *msg_ctx;
87         int msg_type;
88         uint32 msg_flag;
89         const void *buf;
90         size_t len;
91         int n_sent;
92 };
93
94 /****************************************************************************
95  Send one of the messages for the broadcast.
96 ****************************************************************************/
97
98 static int traverse_fn(struct db_record *rec,
99                        const struct connections_key *ckey,
100                        const struct connections_data *crec,
101                        void *state)
102 {
103         struct msg_all *msg_all = (struct msg_all *)state;
104         NTSTATUS status;
105
106         if (crec->cnum != -1)
107                 return 0;
108
109         /* Don't send if the receiver hasn't registered an interest. */
110
111         if(!(crec->bcast_msg_flags & msg_all->msg_flag))
112                 return 0;
113
114         /* If the msg send fails because the pid was not found (i.e. smbd died), 
115          * the msg has already been deleted from the messages.tdb.*/
116
117         status = messaging_send_buf(msg_all->msg_ctx,
118                                     crec->pid, msg_all->msg_type,
119                                     (uint8 *)msg_all->buf, msg_all->len);
120
121         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
122                 
123                 /* If the pid was not found delete the entry from connections.tdb */
124
125                 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
126                          procid_str_static(&crec->pid), crec->cnum,
127                          crec->servicename));
128
129                 rec->delete_rec(rec);
130         }
131         msg_all->n_sent++;
132         return 0;
133 }
134
135 /**
136  * Send a message to all smbd processes.
137  *
138  * It isn't very efficient, but should be OK for the sorts of
139  * applications that use it. When we need efficient broadcast we can add
140  * it.
141  *
142  * @param n_sent Set to the number of messages sent.  This should be
143  * equal to the number of processes, but be careful for races.
144  *
145  * @retval True for success.
146  **/
147 BOOL message_send_all(struct messaging_context *msg_ctx,
148                       int msg_type,
149                       const void *buf, size_t len,
150                       int *n_sent)
151 {
152         struct msg_all msg_all;
153
154         msg_all.msg_type = msg_type;
155         if (msg_type < 1000)
156                 msg_all.msg_flag = FLAG_MSG_GENERAL;
157         else if (msg_type > 1000 && msg_type < 2000)
158                 msg_all.msg_flag = FLAG_MSG_NMBD;
159         else if (msg_type > 2000 && msg_type < 2100)
160                 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
161         else if (msg_type > 2100 && msg_type < 3000)
162                 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
163         else if (msg_type > 3000 && msg_type < 4000)
164                 msg_all.msg_flag = FLAG_MSG_SMBD;
165         else
166                 return False;
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         connections_forall(traverse_fn, &msg_all);
174         if (n_sent)
175                 *n_sent = msg_all.n_sent;
176         return True;
177 }
178
179 struct event_context *messaging_event_context(struct messaging_context *msg_ctx)
180 {
181         return msg_ctx->event_ctx;
182 }
183
184 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 
185                                          struct server_id server_id, 
186                                          struct event_context *ev)
187 {
188         struct messaging_context *ctx;
189         NTSTATUS status;
190
191         if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
192                 return NULL;
193         }
194
195         ctx->id = server_id;
196         ctx->event_ctx = ev;
197
198         status = messaging_tdb_init(ctx, ctx, &ctx->local);
199
200         if (!NT_STATUS_IS_OK(status)) {
201                 DEBUG(0, ("messaging_tdb_init failed: %s\n",
202                           nt_errstr(status)));
203                 TALLOC_FREE(ctx);
204                 return NULL;
205         }
206
207 #ifdef CLUSTER_SUPPORT
208         if (lp_clustering()) {
209                 status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
210
211                 if (!NT_STATUS_IS_OK(status)) {
212                         DEBUG(0, ("messaging_ctdb_init failed: %s\n",
213                                   nt_errstr(status)));
214                         TALLOC_FREE(ctx);
215                         return NULL;
216                 }
217         }
218 #endif
219
220         messaging_register(ctx, NULL, MSG_PING, ping_message);
221
222         /* Register some debugging related messages */
223
224         register_msg_pool_usage(ctx);
225         register_dmalloc_msgs(ctx);
226         debug_register_msgs(ctx);
227
228         return ctx;
229 }
230
231 /*
232  * re-init after a fork
233  */
234 NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
235 {
236 #ifdef CLUSTER_SUPPORT
237
238         TALLOC_FREE(msg_ctx->remote);
239
240         if (lp_clustering()) {
241                 NTSTATUS status;
242
243                 status = messaging_ctdbd_init(msg_ctx, msg_ctx,
244                                               &msg_ctx->remote);
245
246                 if (!NT_STATUS_IS_OK(status)) {
247                         DEBUG(0, ("messaging_ctdb_init failed: %s\n",
248                                   nt_errstr(status)));
249                         return status;
250                 }
251         }
252
253 #endif
254
255         return NT_STATUS_OK;
256 }
257
258
259 /*
260  * Register a dispatch function for a particular message type. Allow multiple
261  * registrants
262 */
263 NTSTATUS messaging_register(struct messaging_context *msg_ctx,
264                             void *private_data,
265                             uint32_t msg_type,
266                             void (*fn)(struct messaging_context *msg,
267                                        void *private_data, 
268                                        uint32_t msg_type, 
269                                        struct server_id server_id,
270                                        DATA_BLOB *data))
271 {
272         struct messaging_callback *cb;
273
274         /*
275          * Only one callback per type
276          */
277
278         for (cb = msg_ctx->callbacks; cb != NULL; cb = cb->next) {
279                 if (cb->msg_type == msg_type) {
280                         cb->fn = fn;
281                         cb->private_data = private_data;
282                         return NT_STATUS_OK;
283                 }
284         }
285
286         if (!(cb = talloc(msg_ctx, struct messaging_callback))) {
287                 return NT_STATUS_NO_MEMORY;
288         }
289
290         cb->msg_type = msg_type;
291         cb->fn = fn;
292         cb->private_data = private_data;
293
294         DLIST_ADD(msg_ctx->callbacks, cb);
295         return NT_STATUS_OK;
296 }
297
298 /*
299   De-register the function for a particular message type.
300 */
301 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
302                           void *private_data)
303 {
304         struct messaging_callback *cb, *next;
305
306         for (cb = ctx->callbacks; cb; cb = next) {
307                 next = cb->next;
308                 if ((cb->msg_type == msg_type)
309                     && (cb->private_data == private_data)) {
310                         DLIST_REMOVE(ctx->callbacks, cb);
311                         TALLOC_FREE(cb);
312                 }
313         }
314 }
315
316 /*
317   Send a message to a particular server
318 */
319 NTSTATUS messaging_send(struct messaging_context *msg_ctx,
320                         struct server_id server, uint32_t msg_type,
321                         const DATA_BLOB *data)
322 {
323         return msg_ctx->local->send_fn(msg_ctx, server, msg_type, data,
324                                        msg_ctx->local);
325 }
326
327 NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
328                             struct server_id server, uint32_t msg_type,
329                             const uint8 *buf, size_t len)
330 {
331         DATA_BLOB blob = data_blob_const(buf, len);
332         return messaging_send(msg_ctx, server, msg_type, &blob);
333 }
334
335 /*
336   Dispatch one messsaging_rec
337 */
338 void messaging_dispatch_rec(struct messaging_context *msg_ctx,
339                             struct messaging_rec *rec)
340 {
341         struct messaging_callback *cb, *next;
342
343         for (cb = msg_ctx->callbacks; cb != NULL; cb = next) {
344                 next = cb->next;
345                 if (cb->msg_type == rec->msg_type) {
346                         cb->fn(msg_ctx, cb->private_data, rec->msg_type,
347                                rec->src, &rec->buf);
348                         return;
349                 }
350         }
351         return;
352 }
353
354 /** @} **/