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
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 2 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 @defgroup messages Internal messaging framework
29 @brief Module for internal messaging between Samba daemons.
31 The idea is that if a part of Samba wants to do communication with
32 another Samba process then it will do a message_register() of a
33 dispatch function, and use message_send_pid() to send messages to
36 The dispatch function is given the pid of the sender, and it can
37 use that to reply by message_send_pid(). See ping_message() for a
40 @caution Dispatch functions must be able to cope with incoming
41 messages on an *odd* byte boundary.
43 This system doesn't have any inherent size limitations but is not
44 very efficient for large messages or when messages are sent in very
50 #include "librpc/gen_ndr/messaging.h"
51 #include "librpc/gen_ndr/ndr_messaging.h"
53 struct messaging_callback
{
54 struct messaging_callback
*prev
, *next
;
56 void (*fn
)(struct messaging_context
*msg
, void *private_data
,
58 struct server_id server_id
, DATA_BLOB
*data
);
62 /****************************************************************************
63 A useful function for testing the message system.
64 ****************************************************************************/
66 static void ping_message(struct messaging_context
*msg_ctx
,
72 const char *msg
= data
->data
? (const char *)data
->data
: "none";
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
);
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 ****************************************************************************/
87 struct messaging_context
*msg_ctx
;
95 /****************************************************************************
96 Send one of the messages for the broadcast.
97 ****************************************************************************/
99 static int traverse_fn(TDB_CONTEXT
*the_tdb
,
100 const struct connections_key
*ckey
,
101 const struct connections_data
*crec
,
104 struct msg_all
*msg_all
= (struct msg_all
*)private_data
;
107 if (crec
->cnum
!= -1)
110 /* Don't send if the receiver hasn't registered an interest. */
112 if(!(crec
->bcast_msg_flags
& msg_all
->msg_flag
))
115 /* If the msg send fails because the pid was not found (i.e. smbd died),
116 * the msg has already been deleted from the messages.tdb.*/
118 status
= messaging_send_buf(msg_all
->msg_ctx
,
119 crec
->pid
, msg_all
->msg_type
,
120 (uint8
*)msg_all
->buf
, msg_all
->len
);
122 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
126 /* If the pid was not found delete the entry from
129 DEBUG(2,("pid %s doesn't exist - deleting connections "
130 "%d [%s]\n", procid_str_static(&crec
->pid
),
131 crec
->cnum
, crec
->servicename
));
133 key
.dptr
= (uint8
*)ckey
;
134 key
.dsize
= sizeof(*ckey
);
136 tdb_delete(the_tdb
, key
);
143 * Send a message to all smbd processes.
145 * It isn't very efficient, but should be OK for the sorts of
146 * applications that use it. When we need efficient broadcast we can add
149 * @param n_sent Set to the number of messages sent. This should be
150 * equal to the number of processes, but be careful for races.
152 * @retval True for success.
154 BOOL
message_send_all(struct messaging_context
*msg_ctx
,
156 const void *buf
, size_t len
,
159 struct msg_all msg_all
;
161 msg_all
.msg_type
= msg_type
;
163 msg_all
.msg_flag
= FLAG_MSG_GENERAL
;
164 else if (msg_type
> 1000 && msg_type
< 2000)
165 msg_all
.msg_flag
= FLAG_MSG_NMBD
;
166 else if (msg_type
> 2000 && msg_type
< 2100)
167 msg_all
.msg_flag
= FLAG_MSG_PRINT_NOTIFY
;
168 else if (msg_type
> 2100 && msg_type
< 3000)
169 msg_all
.msg_flag
= FLAG_MSG_PRINT_GENERAL
;
170 else if (msg_type
> 3000 && msg_type
< 4000)
171 msg_all
.msg_flag
= FLAG_MSG_SMBD
;
178 msg_all
.msg_ctx
= msg_ctx
;
180 connections_forall(traverse_fn
, &msg_all
);
182 *n_sent
= msg_all
.n_sent
;
186 struct event_context
*messaging_event_context(struct messaging_context
*msg_ctx
)
188 return msg_ctx
->event_ctx
;
191 struct messaging_context
*messaging_init(TALLOC_CTX
*mem_ctx
,
192 struct server_id server_id
,
193 struct event_context
*ev
)
195 struct messaging_context
*ctx
;
198 if (!(ctx
= TALLOC_ZERO_P(mem_ctx
, struct messaging_context
))) {
205 status
= messaging_tdb_init(ctx
, ctx
, &ctx
->local
);
207 if (!NT_STATUS_IS_OK(status
)) {
208 DEBUG(0, ("message_init failed: %s\n", nt_errstr(status
)));
212 messaging_register(ctx
, NULL
, MSG_PING
, ping_message
);
214 /* Register some debugging related messages */
216 register_msg_pool_usage(ctx
);
217 register_dmalloc_msgs(ctx
);
218 debug_register_msgs(ctx
);
224 * Register a dispatch function for a particular message type. Allow multiple
227 NTSTATUS
messaging_register(struct messaging_context
*msg_ctx
,
230 void (*fn
)(struct messaging_context
*msg
,
233 struct server_id server_id
,
236 struct messaging_callback
*cb
;
239 * Only one callback per type
242 for (cb
= msg_ctx
->callbacks
; cb
!= NULL
; cb
= cb
->next
) {
243 if (cb
->msg_type
== msg_type
) {
245 cb
->private_data
= private_data
;
250 if (!(cb
= talloc(msg_ctx
, struct messaging_callback
))) {
251 return NT_STATUS_NO_MEMORY
;
254 cb
->msg_type
= msg_type
;
256 cb
->private_data
= private_data
;
258 DLIST_ADD(msg_ctx
->callbacks
, cb
);
263 De-register the function for a particular message type.
265 void messaging_deregister(struct messaging_context
*ctx
, uint32_t msg_type
,
268 struct messaging_callback
*cb
, *next
;
270 for (cb
= ctx
->callbacks
; cb
; cb
= next
) {
272 if ((cb
->msg_type
== msg_type
)
273 && (cb
->private_data
== private_data
)) {
274 DLIST_REMOVE(ctx
->callbacks
, cb
);
281 Send a message to a particular server
283 NTSTATUS
messaging_send(struct messaging_context
*msg_ctx
,
284 struct server_id server
, uint32_t msg_type
,
285 const DATA_BLOB
*data
)
287 return msg_ctx
->local
->send_fn(msg_ctx
, server
, msg_type
, data
,
291 NTSTATUS
messaging_send_buf(struct messaging_context
*msg_ctx
,
292 struct server_id server
, uint32_t msg_type
,
293 const uint8
*buf
, size_t len
)
295 DATA_BLOB blob
= data_blob_const(buf
, len
);
296 return messaging_send(msg_ctx
, server
, msg_type
, &blob
);
300 Dispatch one messsaging_rec
302 void messaging_dispatch_rec(struct messaging_context
*msg_ctx
,
303 struct messaging_rec
*rec
)
305 struct messaging_callback
*cb
, *next
;
307 for (cb
= msg_ctx
->callbacks
; cb
!= NULL
; cb
= next
) {
309 if (cb
->msg_type
== rec
->msg_type
) {
310 cb
->fn(msg_ctx
, cb
->private_data
, rec
->msg_type
,
311 rec
->src
, &rec
->buf
);