diff options
Diffstat (limited to 'mono/Handler.cs')
| -rw-r--r-- | mono/Handler.cs | 256 | 
1 files changed, 256 insertions, 0 deletions
diff --git a/mono/Handler.cs b/mono/Handler.cs new file mode 100644 index 00000000..d565b7ec --- /dev/null +++ b/mono/Handler.cs @@ -0,0 +1,256 @@ +namespace DBus +{ +  using System; +  using System.Runtime.InteropServices; +  using System.Diagnostics; +  using System.Reflection; +  using System.Collections; + +  internal class Handler +  { +    private string[] path = null; +    private string pathName = null; +    private Introspector introspector = null; +    private object handledObject = null; +    private Hashtable handledMethods = null; +    private DBusObjectPathVTable vTable; +    private Connection connection; +    private Service service; +    private DBusHandleMessageFunction filterCalled; +     +    internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection, +							    IntPtr userData); + +    internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection, +							IntPtr rawMessage, +							IntPtr userData); + +    internal delegate int DBusHandleMessageFunction(IntPtr rawConnection, +						    IntPtr rawMessage, +						    IntPtr userData); + + +    private enum Result  +    { +      Handled = 0, +      NotYetHandled = 1, +      NeedMemory = 2 +    } + +    [StructLayout (LayoutKind.Sequential)] +    private struct DBusObjectPathVTable  +    { +      public DBusObjectPathUnregisterFunction unregisterFunction; +      public DBusObjectPathMessageFunction messageFunction; +      public IntPtr padding1; +      public IntPtr padding2; +      public IntPtr padding3; +      public IntPtr padding4; +     +      public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction, +				  DBusObjectPathMessageFunction messageFunction)  +      { +	this.unregisterFunction = unregisterFunction; +	this.messageFunction = messageFunction; +	this.padding1 = IntPtr.Zero; +	this.padding2 = IntPtr.Zero; +	this.padding3 = IntPtr.Zero; +	this.padding4 = IntPtr.Zero; +      } +    } + +    ~Handler()  +    { +      if (Connection != null && Connection.RawConnection != IntPtr.Zero && path != null) { +	dbus_connection_unregister_object_path(Connection.RawConnection, +					       Path); +      }  +    } + +    public Handler(object handledObject,  +		       string pathName,  +		       Service service) +    { +      Service = service; +      Connection = service.Connection; +      HandledObject = handledObject; + +      // Strip the leading / off if there is one and get the path as an array +      pathName = pathName.TrimStart('/'); +      this.path = pathName.Split('/'); +      this.pathName = "/" + pathName; + +      // Create the vTable and register the path +      vTable = new DBusObjectPathVTable(new DBusObjectPathUnregisterFunction(Unregister_Called),  +					new DBusObjectPathMessageFunction(Message_Called)); +       +      if (!dbus_connection_register_object_path(Connection.RawConnection, +						Path, +						ref vTable, +						IntPtr.Zero)) +	throw new OutOfMemoryException(); +       +      // Setup the filter function +      this.filterCalled = new DBusHandleMessageFunction(Filter_Called); +      if (!dbus_connection_add_filter(Connection.RawConnection, +				      this.filterCalled, +				      IntPtr.Zero, +				      IntPtr.Zero)) +	throw new OutOfMemoryException(); +    } + +    private void RegisterMethod(MethodInfo method)  +    { +      string key = method.Name + " " + Arguments.ParseParameters(method); +      handledMethods.Add(key, method); +    } + +    public object HandledObject  +    { +      get  +	{ +	  return this.handledObject; +	} +       +      set +	{ +	  this.handledObject = value; + +	  object[] attributes; + +	  // Register the methods +	  this.handledMethods = new Hashtable(); +	  this.introspector = new Introspector(value.GetType()); +	   +	  foreach (MethodInfo method in this.introspector.Methods) { +	    RegisterMethod(method); +	  }   +	} +    } +     +    public int Filter_Called(IntPtr rawConnection, +			     IntPtr rawMessage, +			     IntPtr userData)  +    { +      Message message = Message.Wrap(rawMessage, Service); +       +      if (message.Type == Message.MessageType.Signal) { +	Signal signal = (Signal) message; +      } else if (message.Type == Message.MessageType.MethodCall) { +	MethodCall methodCall = (MethodCall) message; +      } +       +      return (int) Result.NotYetHandled; +    } + +    public void Unregister_Called(IntPtr rawConnection,  +				  IntPtr userData) +    { +      System.Console.WriteLine("FIXME: Unregister called."); +    } + +    private int Message_Called(IntPtr rawConnection,  +			       IntPtr rawMessage,  +			       IntPtr userData)  +    { +      Message message = Message.Wrap(rawMessage, Service); + +      switch (message.Type) { +      case Message.MessageType.Signal: +	System.Console.WriteLine("FIXME: Signal called."); +	break; +      case Message.MessageType.MethodCall: +	return (int) HandleMethod((MethodCall) message); +      } + +      return (int) Result.NotYetHandled; +    } +     +    private Result HandleMethod(MethodCall methodCall) +    { +      methodCall.Service = service; + +      // Check the interface name matches +      if (methodCall.InterfaceName != this.introspector.InterfaceName) { +	return Result.NotYetHandled; +      } + +      // Iterate through getting the type codes +      string key = methodCall.Name + " " + methodCall.Arguments; + +      // Check it's one of our methods +      if (!handledMethods.Contains(key)) { +	return Result.NotYetHandled; +      } + +      // Got it! +      MethodInfo method = (MethodInfo) handledMethods[key]; + +      // Now call the method. FIXME: Error handling +      object [] args = methodCall.Arguments.GetParameters(method); +      object retVal = method.Invoke(this.handledObject, args); + +      // Create the reply and send it +      MethodReturn methodReturn = new MethodReturn(methodCall); +      methodReturn.Arguments.AppendResults(method, retVal, args); +      methodReturn.Send(); + +      return Result.Handled; +    } + +    internal string[] Path  +    { +      get  +	{ +	  return path; +	} +    } + +    public string PathName +    { +      get +	{ +	  return pathName; +	} +    } + +    internal Connection Connection  +    { +      get +	{ +	  return connection; +	} +       +      set  +	{ +	  this.connection = value; +	} +    } + +    public Service Service +    { +      get +	{ +	  return service; +	} +       +      set  +	{ +	  this.service = value; +	} +    }     + +    [DllImport ("dbus-1")] +    private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string[] path, ref DBusObjectPathVTable vTable, IntPtr userData); + +    [DllImport ("dbus-1")] +    private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string[] path); + +    [DllImport ("dbus-1")] +    private extern static bool dbus_connection_add_filter(IntPtr rawConnection, +							  DBusHandleMessageFunction filter, +							  IntPtr userData, +							  IntPtr freeData); + +  } +}  | 
