public void ReadBooleanArrayBigEndian () { byte[] data = new byte[] { 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 }; MessageReader reader = new MessageReader (EndianFlag.Big, data); bool[] array = (bool[])reader.ReadArray (typeof (bool)); Assert.IsNotNull (array); Assert.AreEqual (4, array.Length, "length"); CollectionAssert.AreEqual (new bool[] { true, false, true, true}, array, "elements"); Assert.IsFalse (reader.DataAvailable); }
public void ReadIntArrayBigEndian () { byte[] data = new byte[] { 0, 0, 0, 16, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 8 }; MessageReader reader = new MessageReader (EndianFlag.Big, data); int[] array = (int[])reader.ReadArray (typeof (int)); Assert.IsNotNull (array); Assert.AreEqual (4, array.Length, "length"); CollectionAssert.AreEqual (new int[] { 0x808, 0x808, 0x808, 0x808}, array, "elements"); Assert.IsFalse (reader.DataAvailable); }
public virtual void HandleMethodCall(MessageContainer method_call) { MethodInfo mi; if (!methodInfoCache.TryGetValue(method_call.Member, out mi)) methodInfoCache[method_call.Member] = mi = Mapper.GetMethod(Object.GetType(), method_call); if (mi == null) { conn.MaybeSendUnknownMethodError(method_call); return; } MethodCaller mCaller; if (!mCallers.TryGetValue(mi, out mCaller)) { mCaller = TypeImplementer.GenCaller(mi); mCallers[mi] = mCaller; } Signature inSig, outSig; TypeImplementer.SigsForMethod(mi, out inSig, out outSig); Message msg = method_call.Message; MessageReader msgReader = new MessageReader(msg); MessageWriter retWriter = new MessageWriter(); Exception raisedException = null; try { mCaller(Object, msgReader, msg, retWriter); } catch (Exception e) { raisedException = e; } if (!msg.ReplyExpected) return; Message replyMsg; if (raisedException == null) { MessageContainer method_return = new MessageContainer { Type = MessageType.MethodReturn, ReplySerial = msg.Header.Serial }; replyMsg = method_return.Message; replyMsg.AttachBodyTo(retWriter); replyMsg.Signature = outSig; } else { // BusException allows precisely formatted Error messages. BusException busException = raisedException as BusException; if (busException != null) replyMsg = 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)) { replyMsg = method_call.CreateError("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine()); } } else replyMsg = method_call.CreateError(Mapper.GetInterfaceName(raisedException.GetType()), raisedException.Message); } if (method_call.Sender != null) replyMsg.Header[FieldCode.Destination] = method_call.Sender; conn.Send(replyMsg); }
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); }
public void ReadIntLongIntStructLittleEndian () { // (ixi) and (1, 2, 3) byte[] data = new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }; MessageReader reader = new MessageReader (EndianFlag.Little, data); TestStruct stct = (TestStruct)reader.ReadStruct (typeof (TestStruct)); Assert.AreEqual (1, stct.Item1); Assert.AreEqual (2, stct.Item2); Assert.AreEqual (3, stct.Item3); }
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 void ReadSameAlignementStructNativeEndian () { // Will test the fast path with mixed types but same alignement byte[] data = new byte[8 * 3]; Array.Copy (BitConverter.GetBytes ((long)1), 0, data, 0, 8); Array.Copy (BitConverter.GetBytes (ulong.MaxValue), 0, data, 8, 8); Array.Copy (BitConverter.GetBytes ((double)3.3), 0, data, 16, 8); MessageReader reader = new MessageReader (BitConverter.IsLittleEndian ? EndianFlag.Little : EndianFlag.Big, data); TestStruct3 stct = (TestStruct3)reader.ReadStruct (typeof (TestStruct3)); Assert.AreEqual (1, stct.Item1); Assert.AreEqual (ulong.MaxValue, stct.Item2); Assert.AreEqual (3.3, stct.Item3); }
public void ReadSameAlignementStructNonNativeEndian () { // Will test the fast path with mixed types but same alignement byte[] data = new byte[8 * 3]; Array.Copy (BitConverter.GetBytes ((long)1), 0, data, 0, 8); Array.Copy (BitConverter.GetBytes (ulong.MaxValue), 0, data, 8, 8); Array.Copy (BitConverter.GetBytes ((double)3.3), 0, data, 16, 8); // Swap value to simulate other endianess for (int i = 0; i < data.Length; i += 8) { for (int j = 0; j < 4; j++) { data[i + j] = (byte)(data[i + j] ^ data[i + 7 - j]); data[i + 7 - j] = (byte)(data[i + j] ^ data[i + 7 - j]); data[i + j] = (byte)(data[i + j] ^ data[i + 7 - j]); } } MessageReader reader = new MessageReader (!BitConverter.IsLittleEndian ? EndianFlag.Little : EndianFlag.Big, data); TestStruct3 stct = (TestStruct3)reader.ReadStruct (typeof (TestStruct3)); Assert.AreEqual (1, stct.Item1); Assert.AreEqual (ulong.MaxValue, stct.Item2); Assert.AreEqual (3.3, stct.Item3); }
public void ReadIntLittleEndian () { MessageReader reader = new MessageReader (EndianFlag.Little, new byte[] { 8, 8, 0, 0}); Assert.AreEqual (0x808, reader.ReadInt32 ()); Assert.IsFalse (reader.DataAvailable); }
public void ReadIntIntIntStructLittleEndianGeneric () { // Will test the fast path byte[] data = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 }; MessageReader reader = new MessageReader (EndianFlag.Little, data); TestStruct2 stct = reader.ReadStruct<TestStruct2> (); Assert.AreEqual (1, stct.Item1); Assert.AreEqual (2, stct.Item2); Assert.AreEqual (3, stct.Item3); }
public void ReadIntLongIntStructNonAlignedLittleEndian () { // (ixi) and (1, 2, 3) byte[] data = new byte[] { 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }; MessageReader reader = new MessageReader (EndianFlag.Little, data); TestStruct stct = (TestStruct)reader.ReadStruct (typeof (TestStruct)); }
public MessageReader SendMethodCall(string iface, string member, string inSigStr, MessageWriter writer, Type retType, out Exception exception) { if (string.IsNullOrEmpty (bus_name)) throw new ArgumentNullException ("bus_name"); if (object_path == null) throw new ArgumentNullException ("object_path"); exception = null; Signature inSig = String.IsNullOrEmpty (inSigStr) ? Signature.Empty : new Signature (inSigStr); MessageContainer method_call = new MessageContainer { Path = object_path, Interface = iface, Member = member, Destination = bus_name, Signature = inSig }; Message callMsg = method_call.Message; callMsg.AttachBodyTo (writer); bool needsReply = true; callMsg.ReplyExpected = needsReply; callMsg.Signature = inSig; if (!needsReply) { conn.Send (callMsg); return null; } #if PROTO_REPLY_SIGNATURE if (needsReply) { Signature outSig = Signature.GetSig (retType); callMsg.Header[FieldCode.ReplySignature] = outSig; } #endif Message retMsg = conn.SendWithReplyAndBlock (callMsg); MessageReader retVal = null; //handle the reply message switch (retMsg.Header.MessageType) { case MessageType.MethodReturn: retVal = new MessageReader (retMsg); break; case MessageType.Error: MessageContainer error = MessageContainer.FromMessage (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 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 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[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; }
public void ReadIntBigEndian () { MessageReader reader = new MessageReader (EndianFlag.Big, new byte[] { 0, 0, 8, 8}); Assert.AreEqual (0x808, reader.ReadInt32 ()); Assert.IsFalse (reader.DataAvailable); }
public object SendMethodCallOld(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[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 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++; } }