5 using System.Runtime.InteropServices;
6 using System.Diagnostics;
7 using System.Collections;
9 public class Message : IDisposable
11 private static Stack stack = new Stack ();
13 static public Message Current {
16 return stack.Count > 0 ? (Message) stack.Peek () : null;
20 static internal void Push (Message message)
25 static internal void Pop ()
32 /// A pointer to the underlying Message structure
34 private IntPtr rawMessage;
37 /// The current slot number
39 private static int slot = -1;
41 // Keep in sync with C
42 public enum MessageType
51 private Arguments arguments = null;
53 protected Service service = null;
54 protected string pathName = null;
55 protected string interfaceName = null;
56 protected string name = null;
57 private string key= null;
61 // An empty constructor for the sake of sub-classes which know how to construct theirselves.
64 protected Message(IntPtr rawMessage, Service service)
66 RawMessage = rawMessage;
67 this.service = service;
70 protected Message(MessageType messageType)
72 // the assignment bumps the refcount
73 RawMessage = dbus_message_new((int) messageType);
75 if (RawMessage == IntPtr.Zero) {
76 throw new OutOfMemoryException();
79 dbus_message_unref(RawMessage);
82 protected Message(MessageType messageType, Service service) : this(messageType)
84 this.service = service;
90 GC.SuppressFinalize(this);
93 public void Dispose (bool disposing)
96 if (this.arguments != null)
97 this.arguments.Dispose ();
100 RawMessage = IntPtr.Zero; // free the native object
108 public static Message Wrap(IntPtr rawMessage, Service service)
111 // If we already have a Message object associated with this rawMessage then return it
112 IntPtr rawThis = dbus_message_get_data(rawMessage, slot);
113 if (rawThis != IntPtr.Zero && ((GCHandle)rawThis).Target == typeof(DBus.Message))
114 return (DBus.Message) ((GCHandle)rawThis).Target;
116 // If it doesn't exist then create a new Message around it
117 Message message = null;
118 MessageType messageType = (MessageType) dbus_message_get_type(rawMessage);
120 switch (messageType) {
121 case MessageType.Signal:
122 message = new Signal(rawMessage, service);
124 case MessageType.MethodCall:
125 message = new MethodCall(rawMessage, service);
127 case MessageType.MethodReturn:
128 message = new MethodReturn(rawMessage, service);
130 case MessageType.Error:
131 message = new ErrorMessage(rawMessage, service);
134 throw new ApplicationException("Unknown message type to wrap: " + messageType);
140 internal IntPtr RawMessage
148 if (value == rawMessage)
151 if (rawMessage != IntPtr.Zero)
153 // Get the reference to this
154 IntPtr rawThis = dbus_message_get_data(rawMessage, Slot);
155 Debug.Assert (rawThis != IntPtr.Zero);
157 // Blank over the reference
158 dbus_message_set_data(rawMessage, Slot, IntPtr.Zero, IntPtr.Zero);
160 // Free the reference
161 ((GCHandle) rawThis).Free();
163 // Unref the connection
164 dbus_message_unref(rawMessage);
167 this.rawMessage = value;
169 if (rawMessage != IntPtr.Zero)
173 dbus_message_ref(rawMessage);
175 // We store a weak reference to the C# object on the C object
176 rawThis = GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection);
178 dbus_message_set_data(rawMessage, Slot, (IntPtr) rawThis, IntPtr.Zero);
183 public void Send(ref int serial)
185 if (!dbus_connection_send (Service.Connection.RawConnection, RawMessage, ref serial))
186 throw new OutOfMemoryException ();
188 Service.Connection.Flush();
197 public void SendWithReply()
199 IntPtr rawPendingCall = IntPtr.Zero;
201 if (!dbus_connection_send_with_reply (Service.Connection.RawConnection, RawMessage, rawPendingCall, Service.Connection.Timeout))
202 throw new OutOfMemoryException();
205 public MethodReturn SendWithReplyAndBlock()
207 Error error = new Error();
210 IntPtr rawMessage = dbus_connection_send_with_reply_and_block(Service.Connection.RawConnection,
212 Service.Connection.Timeout,
215 if (rawMessage != IntPtr.Zero) {
216 MethodReturn methodReturn = new MethodReturn(rawMessage, Service);
217 // Ownership of a ref is passed onto us from
218 // dbus_connection_send_with_reply_and_block(). It gets reffed as
219 // a result of being passed into the MethodReturn ctor, so unref
220 // the extra one here.
221 dbus_message_unref (rawMessage);
225 throw new DBusException(error);
229 public MessageType Type
233 return (MessageType) dbus_message_get_type(RawMessage);
237 public Service Service
241 if (this.service != null && (value.Name != this.service.Name)) {
242 if (!dbus_message_set_destination(RawMessage, value.Name)) {
243 throw new OutOfMemoryException();
247 this.service = value;
255 protected virtual string PathName
259 if (value != this.pathName)
261 if (!dbus_message_set_path(RawMessage, value)) {
262 throw new OutOfMemoryException();
265 this.pathName = value;
270 if (this.pathName == null) {
271 this.pathName = Marshal.PtrToStringAnsi(dbus_message_get_path(RawMessage));
274 return this.pathName;
278 protected virtual string InterfaceName
282 if (value != this.interfaceName)
284 dbus_message_set_interface (RawMessage, value);
285 this.interfaceName = value;
290 if (this.interfaceName == null) {
291 this.interfaceName = Marshal.PtrToStringAnsi(dbus_message_get_interface(RawMessage));
294 return this.interfaceName;
298 protected virtual string Name
301 if (value != this.name) {
302 dbus_message_set_member(RawMessage, value);
307 if (this.name == null) {
308 this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
318 if (this.key == null) {
319 this.key = Name + " " + Arguments;
326 public Arguments Arguments
330 if (this.arguments == null) {
331 this.arguments = new Arguments(this);
334 return this.arguments;
342 return Marshal.PtrToStringAnsi(dbus_message_get_sender(RawMessage));
346 public string Destination
350 return Marshal.PtrToStringAnsi(dbus_message_get_destination(RawMessage));
360 // We need to initialize the slot
361 if (!dbus_message_allocate_data_slot (ref slot))
362 throw new OutOfMemoryException ();
364 Debug.Assert (slot >= 0);
371 [DllImport ("dbus-1", EntryPoint="dbus_message_new")]
372 protected extern static IntPtr dbus_message_new (int messageType);
374 [DllImport ("dbus-1", EntryPoint="dbus_message_unref")]
375 protected extern static void dbus_message_unref (IntPtr ptr);
377 [DllImport ("dbus-1", EntryPoint="dbus_message_ref")]
378 protected extern static void dbus_message_ref (IntPtr ptr);
380 [DllImport ("dbus-1", EntryPoint="dbus_message_allocate_data_slot")]
381 protected extern static bool dbus_message_allocate_data_slot (ref int slot);
383 [DllImport ("dbus-1", EntryPoint="dbus_message_free_data_slot")]
384 protected extern static void dbus_message_free_data_slot (ref int slot);
386 [DllImport ("dbus-1", EntryPoint="dbus_message_set_data")]
387 protected extern static bool dbus_message_set_data (IntPtr ptr,
390 IntPtr free_data_func);
392 [DllImport ("dbus-1", EntryPoint="dbus_message_get_data")]
393 protected extern static IntPtr dbus_message_get_data (IntPtr ptr,
396 [DllImport ("dbus-1", EntryPoint="dbus_connection_send")]
397 private extern static bool dbus_connection_send (IntPtr ptr,
399 ref int client_serial);
401 [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply")]
402 private extern static bool dbus_connection_send_with_reply (IntPtr rawConnection, IntPtr rawMessage, IntPtr rawPendingCall, int timeout);
404 [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply_and_block")]
405 private extern static IntPtr dbus_connection_send_with_reply_and_block (IntPtr rawConnection, IntPtr message, int timeout, ref Error error);
407 [DllImport("dbus-1")]
408 private extern static int dbus_message_get_type(IntPtr rawMessage);
410 [DllImport("dbus-1")]
411 private extern static bool dbus_message_set_path(IntPtr rawMessage, string pathName);
413 [DllImport("dbus-1")]
414 private extern static IntPtr dbus_message_get_path(IntPtr rawMessage);
416 [DllImport("dbus-1")]
417 private extern static bool dbus_message_set_interface (IntPtr rawMessage, string interfaceName);
419 [DllImport("dbus-1")]
420 private extern static IntPtr dbus_message_get_interface(IntPtr rawMessage);
422 [DllImport("dbus-1")]
423 private extern static bool dbus_message_set_member(IntPtr rawMessage, string name);
425 [DllImport("dbus-1")]
426 private extern static IntPtr dbus_message_get_member(IntPtr rawMessage);
428 [DllImport("dbus-1")]
429 private extern static bool dbus_message_set_destination(IntPtr rawMessage, string serviceName);
431 [DllImport("dbus-1")]
432 private extern static IntPtr dbus_message_get_destination(IntPtr rawMessage);
434 [DllImport("dbus-1")]
435 private extern static IntPtr dbus_message_get_sender(IntPtr rawMessage);