Mono.Zeroconf – Rev 1

Subversion Repositories:
Rev:
// Copyright 2006 Alp Toker <alp@atoker.com>
// This software is made available under the MIT License
// See COPYING for details

using System;
using System.Reflection;
using System.Reflection.Emit;

using org.freedesktop.DBus;

namespace NDesk.DBus
{
        //TODO: perhaps ExportObject should not derive from BusObject
        internal class ExportObject : BusObject //, Peer
        {
                public readonly object obj;

                public ExportObject (Connection conn, ObjectPath object_path, object obj) : base (conn, null, object_path)
                {
                        this.obj = obj;
                }

                //maybe add checks to make sure this is not called more than once
                //it's a bit silly as a property
                public bool Registered
                {
                        set {
                                Type type = obj.GetType ();

                                foreach (MemberInfo mi in Mapper.GetPublicMembers (type)) {
                                        EventInfo ei = mi as EventInfo;

                                        if (ei == null)
                                                continue;

                                        Delegate dlg = GetHookupDelegate (ei);

                                        if (value)
                                                ei.AddEventHandler (obj, dlg);
                                        else
                                                ei.RemoveEventHandler (obj, dlg);
                                }
                        }
                }

                public void HandleMethodCall (MethodCall method_call)
                {
                        Type type = obj.GetType ();
                        //object retObj = type.InvokeMember (msg.Member, BindingFlags.InvokeMethod, null, obj, MessageHelper.GetDynamicValues (msg));

                        //TODO: there is no member name mapping for properties etc. yet
                        MethodInfo mi = Mapper.GetMethod (type, method_call);

                        if (mi == null) {
                                conn.MaybeSendUnknownMethodError (method_call);
                                return;
                        }

                        object retObj = null;
                        object[] parmValues = MessageHelper.GetDynamicValues (method_call.message, mi.GetParameters ());

                        try {
                                retObj = mi.Invoke (obj, parmValues);
                        } catch (TargetInvocationException e) {
                                if (!method_call.message.ReplyExpected)
                                        return;

                                Exception ie = e.InnerException;
                                //TODO: complete exception sending support

                                Error error = new Error (Mapper.GetInterfaceName (ie.GetType ()), method_call.message.Header.Serial);
                                error.message.Signature = new Signature (DType.String);

                                MessageWriter writer = new MessageWriter (Connection.NativeEndianness);
                                writer.connection = conn;
                                writer.Write (ie.Message);
                                error.message.Body = writer.ToArray ();

                                //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
                                if (method_call.Sender != null)
                                        error.message.Header.Fields[FieldCode.Destination] = method_call.Sender;

                                conn.Send (error.message);
                                return;
                        }

                        if (method_call.message.ReplyExpected) {
                                Message reply = MessageHelper.ConstructDynamicReply (method_call, mi, retObj, parmValues);
                                conn.Send (reply);
                        }
                }

                /*
                public void Ping ()
                {
                }

                public string GetMachineId ()
                {
                        //TODO: implement this
                        return String.Empty;
                }
                */
        }
}