00001 namespace DBus
00002 {
00003
00004 using System;
00005 using System.Runtime.InteropServices;
00006 using System.Diagnostics;
00007 using System.Collections;
00008
00009 public class Message : IDisposable
00010 {
00011 private static Stack stack = new Stack ();
00012
00013 static public Message Current {
00014 get
00015 {
00016 return stack.Count > 0 ? (Message) stack.Peek () : null;
00017 }
00018 }
00019
00020 static internal void Push (Message message)
00021 {
00022 stack.Push (message);
00023 }
00024
00025 static internal void Pop ()
00026 {
00027 stack.Pop ();
00028 }
00029
00030
00034 private IntPtr rawMessage;
00035
00039 private static int slot = -1;
00040
00041
00042 public enum MessageType
00043 {
00044 Invalid = 0,
00045 MethodCall = 1,
00046 MethodReturn = 2,
00047 Error = 3,
00048 Signal = 4
00049 }
00050
00051 private Arguments arguments = null;
00052
00053 protected Service service = null;
00054 protected string pathName = null;
00055 protected string interfaceName = null;
00056 protected string name = null;
00057 private string key= null;
00058
00059 protected Message()
00060 {
00061
00062 }
00063
00064 protected Message(IntPtr rawMessage, Service service)
00065 {
00066 RawMessage = rawMessage;
00067 this.service = service;
00068 }
00069
00070 protected Message(MessageType messageType)
00071 {
00072
00073 RawMessage = dbus_message_new((int) messageType);
00074
00075 if (RawMessage == IntPtr.Zero) {
00076 throw new OutOfMemoryException();
00077 }
00078
00079 dbus_message_unref(RawMessage);
00080 }
00081
00082 protected Message(MessageType messageType, Service service) : this(messageType)
00083 {
00084 this.service = service;
00085 }
00086
00087 public void Dispose()
00088 {
00089 Dispose(true);
00090 GC.SuppressFinalize(this);
00091 }
00092
00093 public void Dispose (bool disposing)
00094 {
00095 if (disposing) {
00096 if (this.arguments != null)
00097 this.arguments.Dispose ();
00098 }
00099
00100 RawMessage = IntPtr.Zero;
00101 }
00102
00103 ~Message()
00104 {
00105 Dispose (false);
00106 }
00107
00108 public static Message Wrap(IntPtr rawMessage, Service service)
00109 {
00110 if (slot > -1) {
00111
00112 IntPtr rawThis = dbus_message_get_data(rawMessage, slot);
00113 if (rawThis != IntPtr.Zero)
00114 return (DBus.Message) ((GCHandle)rawThis).Target;
00115 }
00116
00117 Message message = null;
00118 MessageType messageType = (MessageType) dbus_message_get_type(rawMessage);
00119
00120 switch (messageType) {
00121 case MessageType.Signal:
00122 message = new Signal(rawMessage, service);
00123 break;
00124 case MessageType.MethodCall:
00125 message = new MethodCall(rawMessage, service);
00126 break;
00127 case MessageType.MethodReturn:
00128 message = new MethodReturn(rawMessage, service);
00129 break;
00130 case MessageType.Error:
00131 message = new ErrorMessage(rawMessage, service);
00132 break;
00133 default:
00134 throw new ApplicationException("Unknown message type to wrap: " + messageType);
00135 }
00136
00137 return message;
00138 }
00139
00140 internal IntPtr RawMessage
00141 {
00142 get
00143 {
00144 return rawMessage;
00145 }
00146 set
00147 {
00148 if (value == rawMessage)
00149 return;
00150
00151 if (rawMessage != IntPtr.Zero)
00152 {
00153
00154 IntPtr rawThis = dbus_message_get_data(rawMessage, Slot);
00155 Debug.Assert (rawThis != IntPtr.Zero);
00156
00157
00158 dbus_message_set_data(rawMessage, Slot, IntPtr.Zero, IntPtr.Zero);
00159
00160
00161 ((GCHandle) rawThis).Free();
00162
00163
00164 dbus_message_unref(rawMessage);
00165 }
00166
00167 this.rawMessage = value;
00168
00169 if (rawMessage != IntPtr.Zero)
00170 {
00171 GCHandle rawThis;
00172
00173 dbus_message_ref(rawMessage);
00174
00175
00176 rawThis = GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection);
00177
00178 dbus_message_set_data(rawMessage, Slot, (IntPtr) rawThis, IntPtr.Zero);
00179 }
00180 }
00181 }
00182
00183 public void Send(ref int serial)
00184 {
00185 if (!dbus_connection_send (Service.Connection.RawConnection, RawMessage, ref serial))
00186 throw new OutOfMemoryException ();
00187
00188 Service.Connection.Flush();
00189 }
00190
00191 public void Send()
00192 {
00193 int ignored = 0;
00194 Send(ref ignored);
00195 }
00196
00197 public void SendWithReply()
00198 {
00199 IntPtr rawPendingCall = IntPtr.Zero;
00200
00201 if (!dbus_connection_send_with_reply (Service.Connection.RawConnection, RawMessage, rawPendingCall, Service.Connection.Timeout))
00202 throw new OutOfMemoryException();
00203 }
00204
00205 public MethodReturn SendWithReplyAndBlock()
00206 {
00207 Error error = new Error();
00208 error.Init();
00209
00210 IntPtr rawMessage = dbus_connection_send_with_reply_and_block(Service.Connection.RawConnection,
00211 RawMessage,
00212 Service.Connection.Timeout,
00213 ref error);
00214
00215 if (rawMessage != IntPtr.Zero) {
00216 MethodReturn methodReturn = new MethodReturn(rawMessage, Service);
00217
00218
00219
00220
00221 dbus_message_unref (rawMessage);
00222
00223 return methodReturn;
00224 } else {
00225 throw new DBusException(error);
00226 }
00227 }
00228
00229 public MessageType Type
00230 {
00231 get
00232 {
00233 return (MessageType) dbus_message_get_type(RawMessage);
00234 }
00235 }
00236
00237 public Service Service
00238 {
00239 set
00240 {
00241 if (this.service != null && (value.Name != this.service.Name)) {
00242 if (!dbus_message_set_destination(RawMessage, value.Name)) {
00243 throw new OutOfMemoryException();
00244 }
00245 }
00246
00247 this.service = value;
00248 }
00249 get
00250 {
00251 return this.service;
00252 }
00253 }
00254
00255 protected virtual string PathName
00256 {
00257 set
00258 {
00259 if (value != this.pathName)
00260 {
00261 if (!dbus_message_set_path(RawMessage, value)) {
00262 throw new OutOfMemoryException();
00263 }
00264
00265 this.pathName = value;
00266 }
00267 }
00268 get
00269 {
00270 if (this.pathName == null) {
00271 this.pathName = Marshal.PtrToStringAnsi(dbus_message_get_path(RawMessage));
00272 }
00273
00274 return this.pathName;
00275 }
00276 }
00277
00278 protected virtual string InterfaceName
00279 {
00280 set
00281 {
00282 if (value != this.interfaceName)
00283 {
00284 dbus_message_set_interface (RawMessage, value);
00285 this.interfaceName = value;
00286 }
00287 }
00288 get
00289 {
00290 if (this.interfaceName == null) {
00291 this.interfaceName = Marshal.PtrToStringAnsi(dbus_message_get_interface(RawMessage));
00292 }
00293
00294 return this.interfaceName;
00295 }
00296 }
00297
00298 protected virtual string Name
00299 {
00300 set {
00301 if (value != this.name) {
00302 dbus_message_set_member(RawMessage, value);
00303 this.name = value;
00304 }
00305 }
00306 get {
00307 if (this.name == null) {
00308 this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
00309 }
00310
00311 return this.name;
00312 }
00313 }
00314
00315 public string Key
00316 {
00317 get {
00318 if (this.key == null) {
00319 this.key = Name + " " + Arguments;
00320 }
00321
00322 return this.key;
00323 }
00324 }
00325
00326 public Arguments Arguments
00327 {
00328 get
00329 {
00330 if (this.arguments == null) {
00331 this.arguments = new Arguments(this);
00332 }
00333
00334 return this.arguments;
00335 }
00336 }
00337
00338 public string Sender
00339 {
00340 get
00341 {
00342 return Marshal.PtrToStringAnsi(dbus_message_get_sender(RawMessage));
00343 }
00344 }
00345
00346 public string Destination
00347 {
00348 get
00349 {
00350 return Marshal.PtrToStringAnsi(dbus_message_get_destination(RawMessage));
00351 }
00352 }
00353
00354 protected int Slot
00355 {
00356 get
00357 {
00358 if (slot == -1)
00359 {
00360
00361 if (!dbus_message_allocate_data_slot (ref slot))
00362 throw new OutOfMemoryException ();
00363
00364 Debug.Assert (slot >= 0);
00365 }
00366
00367 return slot;
00368 }
00369 }
00370
00371 [DllImport ("dbus-1", EntryPoint="dbus_message_new")]
00372 protected extern static IntPtr dbus_message_new (int messageType);
00373
00374 [DllImport ("dbus-1", EntryPoint="dbus_message_unref")]
00375 protected extern static void dbus_message_unref (IntPtr ptr);
00376
00377 [DllImport ("dbus-1", EntryPoint="dbus_message_ref")]
00378 protected extern static void dbus_message_ref (IntPtr ptr);
00379
00380 [DllImport ("dbus-1", EntryPoint="dbus_message_allocate_data_slot")]
00381 protected extern static bool dbus_message_allocate_data_slot (ref int slot);
00382
00383 [DllImport ("dbus-1", EntryPoint="dbus_message_free_data_slot")]
00384 protected extern static void dbus_message_free_data_slot (ref int slot);
00385
00386 [DllImport ("dbus-1", EntryPoint="dbus_message_set_data")]
00387 protected extern static bool dbus_message_set_data (IntPtr ptr,
00388 int slot,
00389 IntPtr data,
00390 IntPtr free_data_func);
00391
00392 [DllImport ("dbus-1", EntryPoint="dbus_message_get_data")]
00393 protected extern static IntPtr dbus_message_get_data (IntPtr ptr,
00394 int slot);
00395
00396 [DllImport ("dbus-1", EntryPoint="dbus_connection_send")]
00397 private extern static bool dbus_connection_send (IntPtr ptr,
00398 IntPtr message,
00399 ref int client_serial);
00400
00401 [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply")]
00402 private extern static bool dbus_connection_send_with_reply (IntPtr rawConnection, IntPtr rawMessage, IntPtr rawPendingCall, int timeout);
00403
00404 [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply_and_block")]
00405 private extern static IntPtr dbus_connection_send_with_reply_and_block (IntPtr rawConnection, IntPtr message, int timeout, ref Error error);
00406
00407 [DllImport("dbus-1")]
00408 private extern static int dbus_message_get_type(IntPtr rawMessage);
00409
00410 [DllImport("dbus-1")]
00411 private extern static bool dbus_message_set_path(IntPtr rawMessage, string pathName);
00412
00413 [DllImport("dbus-1")]
00414 private extern static IntPtr dbus_message_get_path(IntPtr rawMessage);
00415
00416 [DllImport("dbus-1")]
00417 private extern static bool dbus_message_set_interface (IntPtr rawMessage, string interfaceName);
00418
00419 [DllImport("dbus-1")]
00420 private extern static IntPtr dbus_message_get_interface(IntPtr rawMessage);
00421
00422 [DllImport("dbus-1")]
00423 private extern static bool dbus_message_set_member(IntPtr rawMessage, string name);
00424
00425 [DllImport("dbus-1")]
00426 private extern static IntPtr dbus_message_get_member(IntPtr rawMessage);
00427
00428 [DllImport("dbus-1")]
00429 private extern static bool dbus_message_set_destination(IntPtr rawMessage, string serviceName);
00430
00431 [DllImport("dbus-1")]
00432 private extern static IntPtr dbus_message_get_destination(IntPtr rawMessage);
00433
00434 [DllImport("dbus-1")]
00435 private extern static IntPtr dbus_message_get_sender(IntPtr rawMessage);
00436 }
00437 }