//TODO: make use of Locked /* protected bool locked = false; public bool Locked { get { return locked; } } */ public void SetHeaderData (byte[] data) { EndianFlag endianness = (EndianFlag)data[0]; MessageReader reader = new MessageReader (endianness, data); Header = (Header)reader.ReadStruct (typeof (Header)); }
public void ParseHeader () { //GetValue (stream, typeof (Header), out Header); EndianFlag endianness = (EndianFlag)HeaderData[0]; MessageReader reader = new MessageReader (endianness, HeaderData); object valT; reader.GetValueStruct (typeof (Header), out valT); Header = (Header)valT; /* //foreach (HeaderField field in HeaderFields) foreach (KeyValuePair<FieldCode,object> field in Header.Fields) { //Console.WriteLine (field.Key + " = " + field.Value); switch (field.Key) { case FieldCode.Invalid: break; case FieldCode.Path: Path = (ObjectPath)field.Value; break; case FieldCode.Interface: Interface = (string)field.Value; break; case FieldCode.Member: Member = (string)field.Value; break; case FieldCode.ErrorName: ErrorName = (string)field.Value; break; case FieldCode.ReplySerial: ReplySerial = (uint)field.Value; break; case FieldCode.Destination: Destination = (string)field.Value; break; case FieldCode.Sender: Sender = (string)field.Value; break; case FieldCode.Signature: Signature = (Signature)field.Value; break; } } */ }
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); }
public static object[] GetDynamicValues (Message msg, Type[] types) { //TODO: this validation check should provide better information, eg. message dump or a stack trace, or at least the interface/member if (Protocol.Verbose) { Signature expected = Signature.GetSig (types); Signature actual = msg.Signature; if (actual != expected) Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler: " + "Expected '" + expected + "', got '" + actual + "'"); } object[] vals = new object[types.Length]; if (msg.Body != null) { MessageReader reader = new MessageReader (msg); for (int i = 0 ; i != types.Length ; i++) vals[i] = reader.ReadValue (types[i]); } return vals; }
public static object[] GetDynamicValues (Message msg, ParameterInfo[] parms) { //TODO: this validation check should provide better information, eg. message dump or a stack trace, or at least the interface/member /* if (Protocol.Verbose) { Signature expected = Signature.GetSig (types); Signature actual = msg.Signature; if (actual != expected) Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler: " + "Expected '" + expected + "', got '" + actual + "'"); } */ object[] vals = new object[parms.Length]; if (msg.Body != null) { MessageReader reader = new MessageReader (msg); foreach (ParameterInfo parm in parms) { if (parm.IsOut) continue; vals[parm.Position] = reader.ReadValue (parm.ParameterType); } } return vals; }
public object SendMethodCall (string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception) { exception = null; //TODO: don't ignore retVal, exception etc. Signature inSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr); MethodCall method_call = new MethodCall (object_path, iface, member, bus_name, inSig); Message callMsg = method_call.message; callMsg.Body = writer.ToArray (); //Invoke Code:: //TODO: complete out parameter support /* Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ()); Signature outParmSig = Signature.GetSig (outParmTypes); if (outParmSig != Signature.Empty) throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'"); */ Type[] outTypes = new Type[1]; outTypes[0] = retType; //we default to always requiring replies for now, even though unnecessary //this is to make sure errors are handled synchronously //TODO: don't hard code this bool needsReply = true; //if (mi.ReturnType == typeof (void)) // needsReply = false; callMsg.ReplyExpected = needsReply; callMsg.Signature = inSig; if (!needsReply) { conn.Send (callMsg); return null; } #if PROTO_REPLY_SIGNATURE if (needsReply) { Signature outSig = Signature.GetSig (outTypes); callMsg.Header.Fields[FieldCode.ReplySignature] = outSig; } #endif Message retMsg = conn.SendWithReplyAndBlock (callMsg); object retVal = null; //handle the reply message switch (retMsg.Header.MessageType) { case MessageType.MethodReturn: object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes); if (retVals.Length != 0) retVal = retVals[retVals.Length - 1]; break; case MessageType.Error: //TODO: typed exceptions Error error = new Error (retMsg); string errMsg = String.Empty; if (retMsg.Signature.Value.StartsWith ("s")) { MessageReader reader = new MessageReader (retMsg); errMsg = reader.ReadString (); } exception = new Exception (error.ErrorName + ": " + errMsg); break; default: throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error"); } return retVal; }
public void Invoke (MethodBase methodBase, string methodName, object[] inArgs, out object[] outArgs, out object retVal, out Exception exception) { outArgs = new object[0]; retVal = null; exception = null; MethodInfo mi = methodBase as MethodInfo; if (mi != null && mi.IsSpecialName && (methodName.StartsWith ("add_") || methodName.StartsWith ("remove_"))) { string[] parts = methodName.Split (new char[]{'_'}, 2); string ename = parts[1]; Delegate dlg = (Delegate)inArgs[0]; ToggleSignal (Mapper.GetInterfaceName (mi), ename, dlg, parts[0] == "add"); return; } Type[] inTypes = Mapper.GetTypes (ArgDirection.In, mi.GetParameters ()); Signature inSig = Signature.GetSig (inTypes); MethodCall method_call; Message callMsg; //build the outbound method call message { //this bit is error-prone (no null checking) and will need rewriting when DProxy is replaced string iface = null; if (mi != null) iface = Mapper.GetInterfaceName (mi); //map property accessors //TODO: this needs to be done properly, not with simple String.Replace //note that IsSpecialName is also for event accessors, but we already handled those and returned if (mi != null && mi.IsSpecialName) { methodName = methodName.Replace ("get_", "Get"); methodName = methodName.Replace ("set_", "Set"); } method_call = new MethodCall (object_path, iface, methodName, bus_name, inSig); callMsg = method_call.message; if (inArgs != null && inArgs.Length != 0) { MessageWriter writer = new MessageWriter (Connection.NativeEndianness); writer.connection = conn; for (int i = 0 ; i != inTypes.Length ; i++) writer.Write (inTypes[i], inArgs[i]); callMsg.Body = writer.ToArray (); } } //TODO: complete out parameter support /* Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ()); Signature outParmSig = Signature.GetSig (outParmTypes); if (outParmSig != Signature.Empty) throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'"); */ Type[] outTypes = new Type[1]; outTypes[0] = mi.ReturnType; //we default to always requiring replies for now, even though unnecessary //this is to make sure errors are handled synchronously //TODO: don't hard code this bool needsReply = true; //if (mi.ReturnType == typeof (void)) // needsReply = false; callMsg.ReplyExpected = needsReply; callMsg.Signature = inSig; if (!needsReply) { conn.Send (callMsg); return; } #if PROTO_REPLY_SIGNATURE if (needsReply) { Signature outSig = Signature.GetSig (outTypes); callMsg.Header.Fields[FieldCode.ReplySignature] = outSig; } #endif Message retMsg = conn.SendWithReplyAndBlock (callMsg); //handle the reply message switch (retMsg.Header.MessageType) { case MessageType.MethodReturn: object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes); if (retVals.Length != 0) retVal = retVals[retVals.Length - 1]; break; case MessageType.Error: //TODO: typed exceptions Error error = new Error (retMsg); string errMsg = String.Empty; if (retMsg.Signature.Value.StartsWith ("s")) { MessageReader reader = new MessageReader (retMsg); errMsg = reader.ReadString (); } exception = new Exception (error.ErrorName + ": " + errMsg); break; default: throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error"); } return; }
private void FetchUiaDbusNames () { var busNames = new List<string> (); IBus ibus = Bus.Session.GetObject<IBus> (DBusName, new ObjectPath (DBusPath)); // Look for buses that contain DCI.IApplication foreach (string busName in ibus.ListNames ()) { // Reading introspection data hangs on some buses // for unknown reasons, so we call Introspect // asynchronously. Note that we are using // internal dbus-sharp classes. The old // behavior was to spin off threads, but this // triggers a Mono bug on Fedora // (BNC#628639/632133) ObjectPath op = new ObjectPath (DC.Constants.ApplicationPath); MethodCall methodCall = new MethodCall (op, "org.freedesktop.DBus.Introspectable", "Introspect", busName, Signature.Empty); PendingCall pendingCall = Bus.Session.SendWithReply (methodCall.message); pendingCall.Completed += (message) => { MessageReader reader = new MessageReader (message); string data = reader.ReadString (); if (data.Contains (DC.Constants.ApplicationInterfaceName)) busNames.Add ((string)message.Header [FieldCode.Sender]); }; } Thread.Sleep (1000); lock (uiaDbusNamesLock) uiaDbusNames = busNames; }
public static object[] GetDynamicValues (Message msg, Type[] types) { //TODO: this validation check should provide better information, eg. message dump or a stack trace if (Protocol.Verbose) { if (Signature.GetSig (types) != msg.Signature) Console.Error.WriteLine ("Warning: The signature of the message does not match that of the handler"); } object[] vals = new object[types.Length]; if (msg.Body != null) { MessageReader reader = new MessageReader (msg); for (int i = 0 ; i != types.Length ; i++) { object arg; reader.GetValue (types[i], out arg); vals[i] = arg; } } return vals; }
public static void Test(HashSet<ArgMatchTest> a, Message msg) { List<Signature> sigs = new List<Signature> (); sigs.AddRange (msg.Signature.GetParts ()); if (sigs.Count == 0) { a.Clear (); return; } a.RemoveWhere ( delegate (ArgMatchTest t) { return t.ArgNum >= sigs.Count || t.Signature != sigs[t.ArgNum]; } ); // Sorting the list here is not ideal List<ArgMatchTest> tests = new List<ArgMatchTest> (a); tests.Sort ( delegate (ArgMatchTest aa, ArgMatchTest bb) { return aa.ArgNum - bb.ArgNum; } ); if (tests.Count == 0) { a.Clear (); return; } MessageReader reader = new MessageReader (msg); int argNum = 0; foreach (ArgMatchTest test in tests) { if (argNum > test.ArgNum) { // This test cannot pass because a previous test already did. // So we already know it will fail without even trying. // This logic will need to be changed to support wildcards. a.Remove (test); continue; } while (argNum != test.ArgNum) { Signature sig = sigs[argNum]; if (!reader.StepOver (sig)) throw new Exception (); argNum++; } // TODO: Avoid re-reading values int savedPos = reader.pos; if (!reader.ReadValue (test.Signature[0]).Equals (test.Value)) { a.Remove (test); reader.pos = savedPos; continue; } argNum++; } }
public void SetHeaderData(byte[] data) { EndianFlag endianness = (EndianFlag)data[0]; MessageReader reader = new MessageReader (endianness, data); MethodCaller2 mCaller = ExportObject.GetMCaller (hHandler); mCaller (this, reader, null, new MessageWriter ()); }
public object ToType(Type conversionType, IFormatProvider provider) { Signature typeSig = Signature.GetSig (conversionType); if (typeSig != signature) throw new InvalidCastException (); MessageReader reader = new MessageReader (endianness, data); return reader.ReadValue (conversionType); }