//this might need reworking with MulticastDelegate internal void HandleSignal(Message msg) { Signal signal = new Signal(msg); //TODO: this is a hack, not necessary when MatchRule is complete MatchRule rule = new MatchRule(); rule.MessageType = MessageType.Signal; rule.Fields.Add(FieldCode.Interface, new MatchTest(signal.Interface)); rule.Fields.Add(FieldCode.Member, new MatchTest(signal.Member)); rule.Fields.Add(FieldCode.Path, new MatchTest(signal.Path)); Delegate dlg; if (Handlers.TryGetValue(rule, out dlg)) { MethodInfo mi = dlg.GetType().GetMethod("Invoke"); bool compatible = false; Signature inSig, outSig; if (TypeImplementer.SigsForMethod(mi, out inSig, out outSig)) { if (outSig == Signature.Empty && inSig == msg.Signature) { compatible = true; } } if (!compatible) { if (Protocol.Verbose) { Console.Error.WriteLine("Signal argument mismatch: " + signal.Interface + '.' + signal.Member); } return; } try { //signals have no return value dlg.DynamicInvoke(MessageHelper.GetDynamicValues(msg, mi.GetParameters())); } catch (MemberAccessException) { throw; } catch (TargetInvocationException) { if (Protocol.Verbose) { Console.Error.WriteLine("Error: Signal handler threw exception " + signal.Member); } } } else { //TODO: how should we handle this condition? sending an Error may not be appropriate in this case if (Protocol.Verbose) { Console.Error.WriteLine("Warning: No signal handler for " + signal.Member); } } }
public void WriteStructure <T> (T value) { TypeWriter <T> tWriter = TypeImplementer.GetTypeWriter <T> (); tWriter(this, value); }
//this requires a seekable stream for now public unsafe void WriteArray <T> (T[] val) { Type elemType = typeof(T); if (elemType == typeof(byte)) { if (val.Length > Protocol.MaxArrayLength) { throw new Exception("Array length " + val.Length + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes"); } Write((uint)val.Length); stream.Write((byte[])(object)val, 0, val.Length); return; } if (elemType.IsEnum) { elemType = Enum.GetUnderlyingType(elemType); } Signature sigElem = Signature.GetSig(elemType); int fixedSize = 0; if (endianness == Connection.NativeEndianness && elemType.IsValueType && !sigElem.IsStruct && sigElem.GetFixedSize(ref fixedSize)) { int byteLength = fixedSize * val.Length; if (byteLength > Protocol.MaxArrayLength) { throw new Exception("Array length " + byteLength + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes"); } Write((uint)byteLength); WritePad(sigElem.Alignment); GCHandle valHandle = GCHandle.Alloc(val, GCHandleType.Pinned); IntPtr p = valHandle.AddrOfPinnedObject(); byte[] data = new byte[byteLength]; byte * bp = (byte *)p; for (int i = 0; i != byteLength; i++) { data[i] = bp[i]; } stream.Write(data, 0, data.Length); valHandle.Free(); return; } long origPos = stream.Position; Write((uint)0); //advance to the alignment of the element WritePad(sigElem.Alignment); long startPos = stream.Position; TypeWriter <T> tWriter = TypeImplementer.GetTypeWriter <T> (); foreach (T elem in val) { tWriter(this, elem); } long endPos = stream.Position; uint ln = (uint)(endPos - startPos); stream.Position = origPos; if (ln > Protocol.MaxArrayLength) { throw new Exception("Array length " + ln + " exceeds maximum allowed " + Protocol.MaxArrayLength + " bytes"); } Write(ln); stream.Position = endPos; }
public void WriteValueType(object val, Type type) { MethodInfo mi = TypeImplementer.GetWriteMethod(type); mi.Invoke(null, new object[] { this, val }); }
public virtual 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 // FIXME: Inefficient to do this on every call MethodInfo mi = Mapper.GetMethod(type, method_call); if (mi == null) { conn.MaybeSendUnknownMethodError(method_call); return; } MethodCaller2 mCaller; if (!mCallers.TryGetValue(mi, out mCaller)) { //mCaller = TypeImplementer.GenCaller (mi, obj); mCaller = TypeImplementer.GenCaller2(mi); mCallers[mi] = mCaller; } Signature inSig, outSig; TypeImplementer.SigsForMethod(mi, out inSig, out outSig); Message msg = method_call.message; MessageReader msgReader = new MessageReader(method_call.message); MessageWriter retWriter = new MessageWriter(); /* * MessageWriter retWriter = null; * if (msg.ReplyExpected) * retWriter = new MessageWriter (); */ Exception raisedException = null; try { //mCaller (msgReader, method_call.message, retWriter); mCaller(obj, msgReader, method_call.message, retWriter); } catch (Exception e) { raisedException = e; } if (!msg.ReplyExpected) { return; } Message replyMsg; if (raisedException == null) { MethodReturn method_return = new MethodReturn(msg.Header.Serial); replyMsg = method_return.message; replyMsg.Body = retWriter.ToArray(); replyMsg.Signature = outSig; } else { Error error; // BusException allows precisely formatted Error messages. BusException busException = raisedException as BusException; if (busException != null) { error = method_call.CreateError(busException.ErrorName, busException.ErrorMessage); } else if (raisedException is ArgumentException && raisedException.TargetSite.Name == mi.Name) { // Name match trick above is a hack since we don't have the resolved MethodInfo. ArgumentException argException = (ArgumentException)raisedException; using (System.IO.StringReader sr = new System.IO.StringReader(argException.Message)) { error = method_call.CreateError("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine()); } } else { error = method_call.CreateError(Mapper.GetInterfaceName(raisedException.GetType()), raisedException.Message); } replyMsg = error.message; } if (method_call.Sender != null) { replyMsg.Header[FieldCode.Destination] = method_call.Sender; } conn.Send(replyMsg); }