~ubuntu-branches/ubuntu/lucid/tomboy/lucid-proposed

« back to all changes in this revision

Viewing changes to Tomboy/dbus-sharp/dbus-sharp/src/Connection.cs

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-11-22 19:22:17 UTC
  • mfrom: (1.1.8 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20061122192217-odnb17d1ib22okof
Tags: 0.5.1-0ubuntu1
* New upstream release:
  + New Managed D-Bus/DBusSharp (Sebastian Dröge)
  + Additional search interface improvements
  + More secure wrapper script to launch Tomboy.exe
  + Fix panel and TrayIcon resizing
  + Fix 1x1 pixel TrayIcon
  + Removed old tintin image
* debian/control:
  + Update build dependencies
* debian/patches/01-dbus0.9.patch,
  debian/patches/50_tintin.patch,
  debian/patches/51_tomboy-dllmap.patch,
  debian/patches/52_external-dbus-sharp.patch,
  debian/patches/53_tomboy-tray-icon.patch:
  + Dropped, merged upstream
* debian/rules,
  debian/tomboy.desktop:
  + Use upstream's desktop file again after it was fixed now
* debian/rules:
  + DBus service file path workaround removed, it's fixed upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2006 Alp Toker <alp@atoker.com>
 
2
// This software is made available under the MIT License
 
3
// See COPYING for details
 
4
 
 
5
using System;
 
6
using System.Diagnostics;
 
7
using System.Collections.Generic;
 
8
using System.IO;
 
9
 
 
10
using System.Threading;
 
11
 
 
12
using System.Reflection;
 
13
 
 
14
//using Console = System.Diagnostics.Trace;
 
15
 
 
16
namespace NDesk.DBus
 
17
{
 
18
        using Authentication;
 
19
        using Transports;
 
20
 
 
21
        public class Connection
 
22
        {
 
23
                //TODO: reduce/correct visibility of these when appropriate
 
24
                public Stream ns = null;
 
25
                public long SocketHandle;
 
26
 
 
27
                protected Transport transport;
 
28
                public Transport Transport {
 
29
                        get {
 
30
                                return transport;
 
31
                        } set {
 
32
                                transport = value;
 
33
                        }
 
34
                }
 
35
 
 
36
                //TODO: reduce visibility when test-server no longer needs this
 
37
                //protected Connection ()
 
38
                public Connection ()
 
39
                {
 
40
                }
 
41
 
 
42
                public Connection (string address)
 
43
                {
 
44
                        OpenPrivate (address);
 
45
                        Authenticate ();
 
46
                }
 
47
 
 
48
                protected bool isConnected = false;
 
49
                public bool IsConnected
 
50
                {
 
51
                        get {
 
52
                                return isConnected;
 
53
                        }
 
54
                }
 
55
 
 
56
                public static Connection Open (string address)
 
57
                {
 
58
                        Connection conn = new Connection ();
 
59
                        conn.OpenPrivate (address);
 
60
                        conn.Authenticate ();
 
61
 
 
62
                        return conn;
 
63
                }
 
64
 
 
65
                //TODO: reduce visibility when test-server no longer needs this
 
66
                //protected void OpenPrivate (string address)
 
67
                public void OpenPrivate (string address)
 
68
                {
 
69
                        string path;
 
70
                        bool abstr;
 
71
 
 
72
                        if (address == null)
 
73
                                throw new ArgumentNullException ("address");
 
74
 
 
75
                        if (!Address.Parse (address, out path, out abstr))
 
76
                                throw new ArgumentException ("Invalid D-Bus address: '" + address + "'", "address");
 
77
 
 
78
                        Open (path, abstr);
 
79
 
 
80
                        isConnected = true;
 
81
                }
 
82
 
 
83
                void Open (string path, bool abstr)
 
84
                {
 
85
                        //transport = new UnixMonoTransport (path, abstr);
 
86
                        transport = new UnixNativeTransport (path, abstr);
 
87
                        ns = transport.Stream;
 
88
                        SocketHandle = transport.SocketHandle;
 
89
                }
 
90
 
 
91
                public void Authenticate ()
 
92
                {
 
93
                        SaslClient auth = new SaslClient (this);
 
94
                        auth.Run ();
 
95
                        isAuthenticated = true;
 
96
                }
 
97
 
 
98
                protected bool isAuthenticated = false;
 
99
                public bool IsAuthenticated
 
100
                {
 
101
                        get {
 
102
                                return isAuthenticated;
 
103
                        }
 
104
                }
 
105
 
 
106
                protected string unique_name = null;
 
107
                public virtual string UniqueName
 
108
                {
 
109
                        get {
 
110
                                return unique_name;
 
111
                        } set {
 
112
                                if (unique_name != null)
 
113
                                        throw new Exception ("Unique name of a Connection can only be set once");
 
114
                                unique_name = value;
 
115
                        }
 
116
                }
 
117
 
 
118
                //Interlocked.Increment() handles the overflow condition for uint correctly, so it's ok to store the value as an int but cast it to uint
 
119
                protected int serial = 0;
 
120
                protected uint GenerateSerial ()
 
121
                {
 
122
                        //return ++serial;
 
123
                        return (uint)Interlocked.Increment (ref serial);
 
124
                }
 
125
 
 
126
 
 
127
 
 
128
 
 
129
                public Message SendWithReplyAndBlock (Message msg)
 
130
                {
 
131
                        uint id = SendWithReply (msg);
 
132
 
 
133
                        Message retMsg = WaitForReplyTo (id);
 
134
                        DispatchSignals ();
 
135
 
 
136
                        return retMsg;
 
137
                }
 
138
 
 
139
                public uint SendWithReply (Message msg)
 
140
                {
 
141
                        msg.ReplyExpected = true;
 
142
                        return Send (msg);
 
143
                }
 
144
 
 
145
                public uint Send (Message msg)
 
146
                {
 
147
                        msg.Header.Serial = GenerateSerial ();
 
148
 
 
149
                        msg.WriteHeader ();
 
150
 
 
151
                        WriteMessage (msg);
 
152
 
 
153
                        //Outbound.Enqueue (msg);
 
154
                        //temporary
 
155
                        //Flush ();
 
156
 
 
157
                        return msg.Header.Serial;
 
158
                }
 
159
 
 
160
                //could be cleaner
 
161
                protected void WriteMessage (Message msg)
 
162
                {
 
163
                        //Monitor.Enter (ns);
 
164
 
 
165
                        //ns.Write (msg.HeaderData, 0, msg.HeaderSize);
 
166
                        //Console.WriteLine ("headerSize: " + msg.HeaderSize);
 
167
                        //Console.WriteLine ("headerLength: " + msg.HeaderData.Length);
 
168
                        //Console.WriteLine ();
 
169
                        ns.Write (msg.HeaderData, 0, msg.HeaderData.Length);
 
170
                        if (msg.Body != null) {
 
171
                                ns.Write (msg.Body, 0, msg.Body.Length);
 
172
                                //msg.Body.WriteTo (ns);
 
173
                        }
 
174
 
 
175
                        //Monitor.Exit (ns);
 
176
                }
 
177
 
 
178
                protected Queue<Message> Inbound = new Queue<Message> ();
 
179
                /*
 
180
                protected Queue<Message> Outbound = new Queue<Message> ();
 
181
 
 
182
                public void Flush ()
 
183
                {
 
184
                        //should just iterate the enumerator here
 
185
                        while (Outbound.Count != 0) {
 
186
                                Message msg = Outbound.Dequeue ();
 
187
                                WriteMessage (msg);
 
188
                        }
 
189
                }
 
190
 
 
191
                public bool ReadWrite (int timeout_milliseconds)
 
192
                {
 
193
                        //TODO
 
194
 
 
195
                        return true;
 
196
                }
 
197
 
 
198
                public bool ReadWrite ()
 
199
                {
 
200
                        return ReadWrite (-1);
 
201
                }
 
202
 
 
203
                public bool Dispatch ()
 
204
                {
 
205
                        //TODO
 
206
                        Message msg = Inbound.Dequeue ();
 
207
                        //HandleMessage (msg);
 
208
 
 
209
                        return true;
 
210
                }
 
211
 
 
212
                public bool ReadWriteDispatch (int timeout_milliseconds)
 
213
                {
 
214
                        //TODO
 
215
                        return Dispatch ();
 
216
                }
 
217
 
 
218
                public bool ReadWriteDispatch ()
 
219
                {
 
220
                        return ReadWriteDispatch (-1);
 
221
                }
 
222
                */
 
223
 
 
224
                public Message ReadMessage ()
 
225
                {
 
226
                        //Monitor.Enter (ns);
 
227
 
 
228
                        //FIXME: fix reading algorithm to work in one step
 
229
                        //this code is a bit silly and inefficient
 
230
                        //hopefully it's at least correct and avoids polls for now
 
231
 
 
232
                        int read;
 
233
 
 
234
                        byte[] buf = new byte[16];
 
235
                        read = ns.Read (buf, 0, 16);
 
236
 
 
237
                        if (read != 16)
 
238
                                throw new Exception ("Header read length mismatch: " + read + " of expected " + "16");
 
239
 
 
240
                        MemoryStream ms = new MemoryStream ();
 
241
 
 
242
                        ms.Write (buf, 0, 16);
 
243
 
 
244
                        EndianFlag endianness = (EndianFlag)buf[0];
 
245
                        MessageReader reader = new MessageReader (endianness, buf);
 
246
 
 
247
                        //discard the endian byte as we've already read it
 
248
                        byte tmp;
 
249
                        reader.GetValue (out tmp);
 
250
 
 
251
                        //discard message type and flags, which we don't care about here
 
252
                        reader.GetValue (out tmp);
 
253
                        reader.GetValue (out tmp);
 
254
 
 
255
                        byte version;
 
256
                        reader.GetValue (out version);
 
257
 
 
258
                        if (version < Protocol.MinVersion || version > Protocol.MaxVersion)
 
259
                                throw new NotSupportedException ("Protocol version '" + version.ToString () + "' is not supported");
 
260
 
 
261
                        if (Protocol.Verbose)
 
262
                                if (version != Protocol.Version)
 
263
                                        Console.Error.WriteLine ("Warning: Protocol version '" + version.ToString () + "' is not explicitly supported but may be compatible");
 
264
 
 
265
                        uint bodyLength, serial, headerLength;
 
266
                        reader.GetValue (out bodyLength);
 
267
                        reader.GetValue (out serial);
 
268
                        reader.GetValue (out headerLength);
 
269
 
 
270
                        //TODO: remove this limitation
 
271
                        if (bodyLength > Int32.MaxValue || headerLength > Int32.MaxValue)
 
272
                                throw new NotImplementedException ("Long messages are not yet supported");
 
273
 
 
274
                        int bodyLen = (int)bodyLength;
 
275
                        int toRead = (int)headerLength;
 
276
 
 
277
                        toRead = Protocol.Padded ((int)toRead, 8);
 
278
 
 
279
                        buf = new byte[toRead];
 
280
 
 
281
                        read = ns.Read (buf, 0, toRead);
 
282
 
 
283
                        if (read != toRead)
 
284
                                throw new Exception ("Read length mismatch: " + read + " of expected " + toRead);
 
285
 
 
286
                        ms.Write (buf, 0, buf.Length);
 
287
 
 
288
                        Message msg = new Message ();
 
289
                        msg.HeaderData = ms.ToArray ();
 
290
 
 
291
                        //read the body
 
292
                        if (bodyLen != 0) {
 
293
                                //FIXME
 
294
                                //msg.Body = new byte[(int)msg.Header->Length];
 
295
                                byte[] body = new byte[bodyLen];
 
296
 
 
297
                                //int len = ns.Read (msg.Body, 0, msg.Body.Length);
 
298
                                int len = ns.Read (body, 0, bodyLen);
 
299
 
 
300
                                //if (len != msg.Body.Length)
 
301
                                if (len != bodyLen)
 
302
                                        throw new Exception ("Message body size mismatch");
 
303
 
 
304
                                //msg.Body = new MemoryStream (body);
 
305
                                msg.Body = body;
 
306
                        }
 
307
 
 
308
                        //Monitor.Exit (ns);
 
309
 
 
310
                        //this needn't be done here
 
311
                        msg.ParseHeader ();
 
312
 
 
313
                        return msg;
 
314
                }
 
315
 
 
316
                //needs to be done properly
 
317
                public Message WaitForReplyTo (uint id)
 
318
                {
 
319
                        //Message msg = Inbound.Dequeue ();
 
320
                        Message msg;
 
321
 
 
322
                        while ((msg = ReadMessage ()) != null) {
 
323
                                if (msg.Header.Fields.ContainsKey (FieldCode.ReplySerial))
 
324
                                        if ((uint)msg.Header.Fields[FieldCode.ReplySerial] == id)
 
325
                                                return msg;
 
326
 
 
327
                                HandleMessage (msg);
 
328
                        }
 
329
 
 
330
                        return null;
 
331
                }
 
332
 
 
333
 
 
334
                //temporary hack
 
335
                protected void DispatchSignals ()
 
336
                {
 
337
                        lock (Inbound) {
 
338
                                while (Inbound.Count != 0) {
 
339
                                        Message msg = Inbound.Dequeue ();
 
340
                                        HandleSignal (msg);
 
341
                                }
 
342
                        }
 
343
                }
 
344
 
 
345
                //temporary hack
 
346
                public void Iterate ()
 
347
                {
 
348
                        //Message msg = Inbound.Dequeue ();
 
349
                        Message msg = ReadMessage ();
 
350
                        HandleMessage (msg);
 
351
                        DispatchSignals ();
 
352
                }
 
353
 
 
354
                protected void HandleMessage (Message msg)
 
355
                {
 
356
                        switch (msg.Header.MessageType) {
 
357
                                case MessageType.MethodCall:
 
358
                                        MethodCall method_call = new MethodCall (msg);
 
359
                                        HandleMethodCall (method_call);
 
360
                                        break;
 
361
                                case MessageType.MethodReturn:
 
362
                                        MethodReturn method_return = new MethodReturn (msg);
 
363
                                        if (PendingCalls.ContainsKey (method_return.ReplySerial)) {
 
364
                                                //TODO: pending calls
 
365
                                                //return msg;
 
366
                                        }
 
367
                                        //if the signature is empty, it's just a token return message
 
368
                                        if (msg.Signature != Signature.Empty)
 
369
                                                Console.Error.WriteLine ("Warning: Couldn't handle async MethodReturn message for request id " + method_return.ReplySerial + " with signature '" + msg.Signature + "'");
 
370
                                        break;
 
371
                                case MessageType.Error:
 
372
                                        //TODO: better exception handling
 
373
                                        Error error = new Error (msg);
 
374
                                        string errMsg = "";
 
375
                                        if (msg.Signature.Value == "s") {
 
376
                                                MessageReader reader = new MessageReader (msg);
 
377
                                                reader.GetValue (out errMsg);
 
378
                                        }
 
379
                                        //throw new Exception ("Remote Error: Signature='" + msg.Signature.Value + "' " + error.ErrorName + ": " + errMsg);
 
380
                                        //if (Protocol.Verbose)
 
381
                                        Console.Error.WriteLine ("Remote Error: Signature='" + msg.Signature.Value + "' " + error.ErrorName + ": " + errMsg);
 
382
                                        break;
 
383
                                case MessageType.Signal:
 
384
                                        //HandleSignal (msg);
 
385
                                        lock (Inbound)
 
386
                                                Inbound.Enqueue (msg);
 
387
                                        break;
 
388
                                case MessageType.Invalid:
 
389
                                default:
 
390
                                        throw new Exception ("Invalid message received: MessageType='" + msg.Header.MessageType + "'");
 
391
                        }
 
392
                }
 
393
 
 
394
                protected Dictionary<uint,Message> PendingCalls = new Dictionary<uint,Message> ();
 
395
 
 
396
 
 
397
                //this might need reworking with MulticastDelegate
 
398
                protected void HandleSignal (Message msg)
 
399
                {
 
400
                        Signal signal = new Signal (msg);
 
401
 
 
402
                        string matchRule = MessageFilter.CreateMatchRule (MessageType.Signal, signal.Path, signal.Interface, signal.Member);
 
403
 
 
404
                        if (Handlers.ContainsKey (matchRule)) {
 
405
                                Delegate dlg = Handlers[matchRule];
 
406
                                //dlg.DynamicInvoke (GetDynamicValues (msg));
 
407
 
 
408
                                MethodInfo mi = dlg.Method;
 
409
                                //signals have no return value
 
410
                                dlg.DynamicInvoke (MessageHelper.GetDynamicValues (msg, mi.GetParameters ()));
 
411
 
 
412
                        } else {
 
413
                                //TODO: how should we handle this condition? sending an Error may not be appropriate in this case
 
414
                                if (Protocol.Verbose)
 
415
                                        Console.Error.WriteLine ("Warning: No signal handler for " + signal.Member);
 
416
                        }
 
417
                }
 
418
 
 
419
                public Dictionary<string,Delegate> Handlers = new Dictionary<string,Delegate> ();
 
420
 
 
421
                //not particularly efficient and needs to be generalized
 
422
                protected void HandleMethodCall (MethodCall method_call)
 
423
                {
 
424
                        //Console.Error.WriteLine ("method_call destination: " + method_call.Destination);
 
425
                        //Console.Error.WriteLine ("method_call path: " + method_call.Path);
 
426
 
 
427
                        //TODO: Ping and Introspect need to be abstracted and moved somewhere more appropriate once message filter infrastructure is complete
 
428
 
 
429
                        if (method_call.Interface == "org.freedesktop.DBus.Peer" && method_call.Member == "Ping") {
 
430
                                object[] pingRet = new object[0];
 
431
                                Message reply = MessageHelper.ConstructReplyFor (method_call, pingRet);
 
432
                                Send (reply);
 
433
                                return;
 
434
                        }
 
435
 
 
436
                        if (method_call.Interface == "org.freedesktop.DBus.Introspectable" && method_call.Member == "Introspect") {
 
437
                                Introspector intro = new Introspector ();
 
438
                                intro.root_path = method_call.Path;
 
439
                                //FIXME: do this properly
 
440
                                foreach (ObjectPath pth in RegisteredObjects.Keys) {
 
441
                                        if (pth.Value.StartsWith (method_call.Path.Value)) {
 
442
                                                intro.target_path = pth;
 
443
                                                intro.target_type = RegisteredObjects[pth].GetType ();
 
444
                                        }
 
445
                                }
 
446
                                intro.HandleIntrospect ();
 
447
                                //Console.Error.WriteLine (intro.xml);
 
448
 
 
449
                                object[] introRet = new object[1];
 
450
                                introRet[0] = intro.xml;
 
451
                                Message reply = MessageHelper.ConstructReplyFor (method_call, introRet);
 
452
                                Send (reply);
 
453
                                return;
 
454
                        }
 
455
 
 
456
                        if (RegisteredObjects.ContainsKey (method_call.Path)) {
 
457
                                object obj = RegisteredObjects[method_call.Path];
 
458
                                Type type = obj.GetType ();
 
459
                                //object retObj = type.InvokeMember (msg.Member, BindingFlags.InvokeMethod, null, obj, MessageHelper.GetDynamicValues (msg));
 
460
 
 
461
                                string methodName = method_call.Member;
 
462
 
 
463
                                //map property accessors
 
464
                                //FIXME: this needs to be done properly, not with simple String.Replace
 
465
                                //special case for Notifications left as a reminder that this is broken
 
466
                                if (method_call.Interface == "org.freedesktop.Notifications") {
 
467
                                        methodName = methodName.Replace ("Get", "get_");
 
468
                                        methodName = methodName.Replace ("Set", "set_");
 
469
                                }
 
470
 
 
471
                                //FIXME: breaks for overloaded methods
 
472
                                MethodInfo mi = type.GetMethod (methodName, BindingFlags.Public | BindingFlags.Instance);
 
473
 
 
474
                                //TODO: send errors instead of passing up local exceptions for these
 
475
 
 
476
                                if (mi == null)
 
477
                                        throw new Exception ("The requested method could not be resolved");
 
478
 
 
479
                                //FIXME: such a simple approach won't work unfortunately
 
480
                                //if (!Mapper.IsPublic (mi))
 
481
                                //      throw new Exception ("The resolved method is not marked as being public on this bus");
 
482
 
 
483
                                object retObj = null;
 
484
                                try {
 
485
                                        object[] inArgs = MessageHelper.GetDynamicValues (method_call.message, mi.GetParameters ());
 
486
                                        retObj = mi.Invoke (obj, inArgs);
 
487
                                } catch (TargetInvocationException e) {
 
488
                                        //TODO: consider whether it's correct to send an error for calls that don't expect a reply
 
489
 
 
490
                                        //TODO: complete exception sending support
 
491
                                        //TODO: method not found etc. exceptions
 
492
                                        Exception ie = e.InnerException;
 
493
                                        if (Protocol.Verbose) {
 
494
                                                Console.Error.WriteLine ();
 
495
                                                Console.Error.WriteLine (ie);
 
496
                                                Console.Error.WriteLine ();
 
497
                                        }
 
498
 
 
499
                                        if (!method_call.message.ReplyExpected) {
 
500
                                                Console.Error.WriteLine ();
 
501
                                                Console.Error.WriteLine ("Warning: Not sending Error message (" + ie.GetType ().Name + ") as reply because no reply was expected by call to '" + (method_call.Interface + "." + method_call.Member) + "'");
 
502
                                                Console.Error.WriteLine ();
 
503
                                                return;
 
504
                                        }
 
505
 
 
506
                                        Error error = new Error (Mapper.GetInterfaceName (ie.GetType ()), method_call.message.Header.Serial);
 
507
                                        error.message.Signature = new Signature (DType.String);
 
508
 
 
509
                                        MessageWriter writer = new MessageWriter ();
 
510
                                        writer.Write (ie.Message);
 
511
                                        error.message.Body = writer.ToArray ();
 
512
 
 
513
                                        //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
 
514
                                        if (method_call.Sender != null)
 
515
                                                error.message.Header.Fields[FieldCode.Destination] = method_call.Sender;
 
516
 
 
517
                                        error.message.Header.Fields[FieldCode.Interface] = method_call.Interface;
 
518
                                        error.message.Header.Fields[FieldCode.Member] = method_call.Member;
 
519
 
 
520
                                        Send (error.message);
 
521
                                        return;
 
522
                                }
 
523
 
 
524
                                if (method_call.message.ReplyExpected) {
 
525
                                        /*
 
526
                                        object[] retObjs;
 
527
 
 
528
                                        if (retObj == null) {
 
529
                                                retObjs = new object[0];
 
530
                                        } else {
 
531
                                                retObjs = new object[1];
 
532
                                                retObjs[0] = retObj;
 
533
                                        }
 
534
 
 
535
                                        Message reply = ConstructReplyFor (method_call, retObjs);
 
536
                                        */
 
537
                                        Message reply = MessageHelper.ConstructReplyFor (method_call, mi.ReturnType, retObj);
 
538
                                        Send (reply);
 
539
                                }
 
540
                        } else {
 
541
                                //FIXME: send the appropriate Error message
 
542
                                Console.Error.WriteLine ("Warning: No method handler for " + method_call.Member);
 
543
                        }
 
544
                }
 
545
 
 
546
                protected Dictionary<ObjectPath,object> RegisteredObjects = new Dictionary<ObjectPath,object> ();
 
547
 
 
548
                //FIXME: this shouldn't be part of the core API
 
549
                //that also applies to much of the other object mapping code
 
550
                //it should cache proxies and objects, really
 
551
 
 
552
                //inspired by System.Activator
 
553
                public object GetObject (Type type, string bus_name, ObjectPath path)
 
554
                {
 
555
                        BusObject busObject = new BusObject (this, bus_name, path);
 
556
                        DProxy prox = new DProxy (busObject, type);
 
557
                        return prox.GetTransparentProxy ();
 
558
                }
 
559
 
 
560
                /*
 
561
                public object GetObject (Type type, string bus_name, ObjectPath path)
 
562
                {
 
563
                        return BusObject.GetObject (this, bus_name, path, type);
 
564
                }
 
565
                */
 
566
 
 
567
                public T GetObject<T> (string bus_name, ObjectPath path)
 
568
                {
 
569
                        return (T)GetObject (typeof (T), bus_name, path);
 
570
                }
 
571
 
 
572
                public void Register (string bus_name, ObjectPath path, object obj)
 
573
                {
 
574
                        Type type = obj.GetType ();
 
575
 
 
576
                        BusObject busObject = new BusObject (this, bus_name, path);
 
577
 
 
578
                        foreach (EventInfo ei in type.GetEvents (BindingFlags.Public | BindingFlags.Instance)) {
 
579
                                //hook up only events that are public to the bus
 
580
                                if (!Mapper.IsPublic (ei))
 
581
                                        continue;
 
582
 
 
583
                                Delegate dlg = busObject.GetHookupDelegate (ei);
 
584
                                ei.AddEventHandler (obj, dlg);
 
585
                        }
 
586
 
 
587
                        //FIXME: implement some kind of tree data structure or internal object hierarchy. right now we are ignoring the name and putting all object paths in one namespace, which is bad
 
588
                        RegisteredObjects[path] = obj;
 
589
                }
 
590
 
 
591
                public object Unregister (string bus_name, ObjectPath path)
 
592
                {
 
593
                        //TODO: make use of bus_name
 
594
 
 
595
                        if (!RegisteredObjects.ContainsKey (path))
 
596
                                throw new Exception ("Cannot unmarshal " + path + " as it isn't marshaled");
 
597
                        object obj = RegisteredObjects[path];
 
598
 
 
599
                        RegisteredObjects.Remove (path);
 
600
 
 
601
                        //FIXME: complete unmarshaling including the handlers we added etc.
 
602
 
 
603
                        return obj;
 
604
                }
 
605
 
 
606
                //these look out of place, but are useful
 
607
                public virtual void AddMatch (string rule)
 
608
                {
 
609
                }
 
610
 
 
611
                public virtual void RemoveMatch (string rule)
 
612
                {
 
613
                }
 
614
 
 
615
                static Connection ()
 
616
                {
 
617
                        if (BitConverter.IsLittleEndian)
 
618
                                NativeEndianness = EndianFlag.Little;
 
619
                        else
 
620
                                NativeEndianness = EndianFlag.Big;
 
621
                }
 
622
 
 
623
                public static readonly EndianFlag NativeEndianness;
 
624
        }
 
625
}