diff options
Diffstat (limited to 'mono/Message.cs')
| -rw-r--r-- | mono/Message.cs | 419 | 
1 files changed, 324 insertions, 95 deletions
diff --git a/mono/Message.cs b/mono/Message.cs index 8f6db007..2f5270dd 100644 --- a/mono/Message.cs +++ b/mono/Message.cs @@ -1,129 +1,358 @@ -namespace DBus { +namespace DBus  +{    using System;    using System.Runtime.InteropServices;    using System.Diagnostics; +  using System.Collections; -  public class Message { +  public class Message  +  { +     +    /// <summary> +    /// A pointer to the underlying Message structure +    /// </summary> +    private IntPtr rawMessage; +     +    /// <summary> +    /// The current slot number +    /// </summary> +    private static int slot = -1; +     +    // Keep in sync with C +    public enum MessageType  +    { +      Invalid = 0, +      MethodCall = 1, +      MethodReturn = 2, +      Error = 3, +      Signal = 4 +    } -    public Message (string name, -                    string dest_service) { +    private Arguments arguments = null; + +    protected Service service = null; +    protected string pathName = null; +    protected string interfaceName = null; +    protected string name = null;     + +    protected Message() +    { +      // An empty constructor for the sake of sub-classes which know how to construct theirselves. +    } +     +    protected Message(IntPtr rawMessage, Service service) +    { +      RawMessage = rawMessage; +      this.service = service; +    } +     +    protected Message(MessageType messageType)  +    {        // the assignment bumps the refcount -      raw = dbus_message_new (name, dest_service); -      if (raw == IntPtr.Zero) -        throw new OutOfMemoryException (); -      dbus_message_unref (raw); +      RawMessage = dbus_message_new((int) messageType); +       +      if (RawMessage == IntPtr.Zero) { +	throw new OutOfMemoryException(); +      } +       +      dbus_message_unref(RawMessage);      } - -    public string Name { -      get { -        return dbus_message_get_name (raw); +     +    protected Message(MessageType messageType, Service service) : this(messageType)  +    { +      this.service = service; +    } +     +    ~Message()  +    { +      RawMessage = IntPtr.Zero; // free the native object +    } +     +    public static Message Wrap(IntPtr rawMessage, Service service)  +    { +      if (slot > -1) { +	// If we already have a Message object associated with this rawMessage then return it +	IntPtr rawThis = dbus_message_get_data(rawMessage, slot); +	if (rawThis != IntPtr.Zero) +	  return (DBus.Message) ((GCHandle)rawThis).Target; +      }  +      // If it doesn't exist then create a new Message around it +      Message message = null; +       +      switch ((MessageType) dbus_message_get_type(rawMessage)) { +      case MessageType.Signal: +	message = new Signal(rawMessage, service); +	break; +      case MessageType.MethodCall: +	message = new MethodCall(rawMessage, service); +	break;        } + +      return message; +    } +     +    internal IntPtr RawMessage  +    { +      get  +	{ +	  return rawMessage; +	} +      set  +	{ +	  if (value == rawMessage)  +	    return; +	   +	  if (rawMessage != IntPtr.Zero)  +	    { +	      // Get the reference to this +	      IntPtr rawThis = dbus_message_get_data(rawMessage, Slot); +	      Debug.Assert (rawThis != IntPtr.Zero); +	       +	      // Blank over the reference +	      dbus_message_set_data(rawMessage, Slot, IntPtr.Zero, IntPtr.Zero); +	       +	      // Free the reference +	      ((GCHandle) rawThis).Free(); +	       +	      // Unref the connection +	      dbus_message_unref(rawMessage); +	    } +	   +	  this.rawMessage = value; +	   +	  if (rawMessage != IntPtr.Zero)  +	    { +	      GCHandle rawThis; +	       +	      dbus_message_ref(rawMessage); +	       +	      // We store a weak reference to the C# object on the C object +	      rawThis = GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection); +	       +	      dbus_message_set_data(rawMessage, Slot, (IntPtr) rawThis, IntPtr.Zero); +	    } +	} +    } +     +    public void Send(ref int serial)  +    { +      if (!dbus_connection_send (Service.Connection.RawConnection, RawMessage, ref serial)) +	throw new OutOfMemoryException (); +    } +     +    public void Send()  +    { +      int ignored = 0; +      Send(ref ignored);      } -    public static Message Wrap (IntPtr ptr) { -      IntPtr gch_ptr; +    public void SendWithReply()  +    { +      IntPtr rawPendingCall = IntPtr.Zero; -      gch_ptr = dbus_message_get_data (ptr, wrapper_slot); -      if (gch_ptr != IntPtr.Zero) { -        return (DBus.Message) ((GCHandle)gch_ptr).Target; -      } else { -        return new Message (ptr); -      } +      if (!dbus_connection_send_with_reply (Service.Connection.RawConnection, RawMessage, rawPendingCall, Service.Connection.Timeout)) +	throw new OutOfMemoryException();      } +      +    public MethodReturn SendWithReplyAndBlock() +    { +      Error error = new Error(); +      error.Init(); -    // surely there's a convention for this pattern with the property -    // and the real member -    IntPtr raw_; -    internal IntPtr raw { -      get { -        return raw_;  -      } -      set { -        if (value == raw_) -          return; -         -        if (raw_ != IntPtr.Zero) { -          IntPtr gch_ptr; -           -          gch_ptr = dbus_message_get_data (raw_, -                                           wrapper_slot); -          Debug.Assert (gch_ptr != IntPtr.Zero); - -          dbus_message_set_data (raw_, wrapper_slot, -                                 IntPtr.Zero, IntPtr.Zero); -           -          ((GCHandle) gch_ptr).Free (); -           -          dbus_message_unref (raw_); -        } -         -        raw_ = value; - -        if (raw_ != IntPtr.Zero) { -          GCHandle gch; - -          dbus_message_ref (raw_); - -          // We store a weak reference to the C# object on the C object -          gch = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection); -           -          dbus_message_set_data (raw_, wrapper_slot, -                                 (IntPtr) gch, IntPtr.Zero); -        } +      IntPtr rawMessage = dbus_connection_send_with_reply_and_block(Service.Connection.RawConnection,  +								    RawMessage,  +								    Service.Connection.Timeout,  +								    ref error); + +      if (rawMessage != IntPtr.Zero) { +	MethodReturn methodReturn = new MethodReturn(rawMessage, Service); +	return methodReturn; +      } else { +	throw new DBusException(error);        }      } -    ~Message () { -      raw = IntPtr.Zero; // free the native object +    public MessageType Type +    { +      get  +	{ +	  return (MessageType) dbus_message_get_type(RawMessage); +	}      } -    Message (IntPtr r) { -      raw = r; +    public Service Service +    { +      set  +	{ +	  if (this.service != null && (value.Name != this.service.Name)) { +	    if (!dbus_message_set_destination(RawMessage, value.Name)) { +	      throw new OutOfMemoryException(); +	    } +	  } +	   +	  this.service = value; +	} +      get  +	{ +	  return this.service; +	}      } -    // static constructor runs before any methods  -    static Message () { -      DBus.Internals.Init (); -       -      Debug.Assert (wrapper_slot == -1); -       -      if (!dbus_message_allocate_data_slot (ref wrapper_slot)) -        throw new OutOfMemoryException (); +    protected virtual string PathName +    { +      set  +	{ +	  if (value != this.pathName)  +	    { +	      if (!dbus_message_set_path(RawMessage, value)) { +		throw new OutOfMemoryException(); +	      } +	       +	      this.pathName = value; +	    } +	} +      get  +	{ +	  if (this.pathName == null) { +	    this.pathName = Marshal.PtrToStringAnsi(dbus_message_get_path(RawMessage)); +	  } +	   +	  return this.pathName; +	} +    } +     +    protected virtual string InterfaceName +    { +      set  +	{ +	  if (value != this.interfaceName) +	    { +	      dbus_message_set_interface (RawMessage, value); +	      this.interfaceName = value; +	    } +	} +      get  +	{ +	  if (this.interfaceName == null) { +	    this.interfaceName = Marshal.PtrToStringAnsi(dbus_message_get_interface(RawMessage)); +	  } -      Debug.Assert (wrapper_slot >= 0); +	  return this.interfaceName; +	}      } +     +    protected virtual string Name +    { +      set  +	{ +	  if (value != this.name) +	    { +	      dbus_message_set_member (RawMessage, value); +	      this.name = value; +	    } +	} +      get  +	{ +	  if (this.name == null) { +	    this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage)); +	  } + -    // slot used to store the C# object on the C object -    static int wrapper_slot = -1; +	  return this.name; +	} +    } + +    public Arguments Arguments +    { +      get  +	{ +	  if (this.arguments == null) { +	    this.arguments = new Arguments(this); +	  } +	   +	  return this.arguments; +	} +    } + +    protected int Slot +    { +      get  +	{ +	  if (slot == -1)  +	    { +	      // We need to initialize the slot +	      if (!dbus_message_allocate_data_slot (ref slot)) +		throw new OutOfMemoryException (); +	       +	      Debug.Assert (slot >= 0); +	    } +	   +	  return slot; +	} +    } +     +    [DllImport ("dbus-1", EntryPoint="dbus_message_new")] +    protected extern static IntPtr dbus_message_new (int messageType); +     +    [DllImport ("dbus-1", EntryPoint="dbus_message_unref")] +    protected extern static void dbus_message_unref (IntPtr ptr); +     +    [DllImport ("dbus-1", EntryPoint="dbus_message_ref")] +    protected extern static void dbus_message_ref (IntPtr ptr); +     +    [DllImport ("dbus-1", EntryPoint="dbus_message_allocate_data_slot")] +    protected extern static bool dbus_message_allocate_data_slot (ref int slot); +     +    [DllImport ("dbus-1", EntryPoint="dbus_message_free_data_slot")] +    protected extern static void dbus_message_free_data_slot (ref int slot); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_new")] -      private extern static IntPtr dbus_message_new (string name, -                                                     string dest_service); +    [DllImport ("dbus-1", EntryPoint="dbus_message_set_data")] +    protected extern static bool dbus_message_set_data (IntPtr ptr, +							int    slot, +							IntPtr data, +							IntPtr free_data_func); +     +    [DllImport ("dbus-1", EntryPoint="dbus_message_get_data")] +    protected extern static IntPtr dbus_message_get_data (IntPtr ptr, +							  int    slot); +     +    [DllImport ("dbus-1", EntryPoint="dbus_connection_send")] +    private extern static bool dbus_connection_send (IntPtr  ptr, +						     IntPtr  message, +						     ref int client_serial); + +    [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply")] +    private extern static bool dbus_connection_send_with_reply (IntPtr rawConnection, IntPtr rawMessage, IntPtr rawPendingCall, int timeout); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_unref")] -      private extern static void dbus_message_unref (IntPtr ptr); +    [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply_and_block")] +    private extern static IntPtr dbus_connection_send_with_reply_and_block (IntPtr rawConnection, IntPtr  message, int timeout, ref Error error); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_ref")] -      private extern static void dbus_message_ref (IntPtr ptr); +    [DllImport("dbus-1")] +    private extern static int dbus_message_get_type(IntPtr rawMessage); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_get_name")] -      private extern static string dbus_message_get_name (IntPtr ptr); +    [DllImport("dbus-1")] +    private extern static bool dbus_message_set_path(IntPtr rawMessage, string pathName); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_allocate_data_slot")] -      private extern static bool dbus_message_allocate_data_slot (ref int slot); +    [DllImport("dbus-1")] +    private extern static IntPtr dbus_message_get_path(IntPtr rawMessage); +     +    [DllImport("dbus-1")] +    private extern static bool dbus_message_set_interface (IntPtr rawMessage, string interfaceName); + +    [DllImport("dbus-1")] +    private extern static IntPtr dbus_message_get_interface(IntPtr rawMessage); +     +    [DllImport("dbus-1")] +    private extern static bool dbus_message_set_member (IntPtr rawMessage, string name); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_free_data_slot")] -      private extern static void dbus_message_free_data_slot (ref int slot); +    [DllImport("dbus-1")] +    private extern static IntPtr dbus_message_get_member(IntPtr rawMessage); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_set_data")] -      private extern static bool dbus_message_set_data (IntPtr ptr, -                                                        int    slot, -                                                        IntPtr data, -                                                        IntPtr free_data_func); +    [DllImport("dbus-1")] +    private extern static bool dbus_message_set_destination(IntPtr rawMessage, string serviceName); -    [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_get_data")] -      private extern static IntPtr dbus_message_get_data (IntPtr ptr, -                                                          int    slot); +    [DllImport("dbus-1")] +    private extern static IntPtr dbus_message_get_destination(IntPtr rawMessage);    }  }  | 
