Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        public void SendSignal(MethodInfo mi, string @interface, string member, object[] outValues)
        {
            //TODO: make use of bus_name?

            Type[]    outTypes = Mapper.GetTypes(ArgDirection.In, mi.GetParameters());
            Signature outSig   = Signature.GetSig(outTypes);

            Signal signal = new Signal(object_path, @interface, member);

            signal.message.Signature = outSig;

            if (outValues != null && outValues.Length != 0)
            {
                MessageWriter writer = new MessageWriter(Connection.NativeEndianness);
                writer.connection = conn;

                for (int i = 0; i != outTypes.Length; i++)
                {
                    writer.Write(outTypes[i], outValues[i]);
                }

                signal.message.Body = writer.ToArray();
            }

            conn.Send(signal.message);
        }
Ejemplo n.º 3
0
        public void WriteProperty(PropertyInfo pri)
        {
            //expose properties as dbus properties
            writer.WriteStartElement("property");
            writer.WriteAttributeString("name", pri.Name);
            writer.WriteAttributeString("type", Signature.GetSig(pri.PropertyType).Value);
            string access = (pri.CanRead ? "read" : String.Empty) + (pri.CanWrite ? "write" : String.Empty);

            writer.WriteAttributeString("access", access);
            WriteAnnotations(pri);
            writer.WriteEndElement();

            //expose properties as methods also
            //it may not be worth doing this in the long run

            /*
             * if (pri.CanRead) {
             *      writer.WriteStartElement ("method");
             *      writer.WriteAttributeString ("name", "Get" + pri.Name);
             *      WriteArgReverse (pri.GetGetMethod ().ReturnParameter);
             *      writer.WriteEndElement ();
             * }
             *
             * if (pri.CanWrite) {
             *      writer.WriteStartElement ("method");
             *      writer.WriteAttributeString ("name", "Set" + pri.Name);
             *      foreach (ParameterInfo pi in pri.GetSetMethod ().GetParameters ())
             *              WriteArg (pi);
             *      writer.WriteEndElement ();
             * }
             */
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        //should generalize this method
        //it is duplicated in DProxy
        public static Message ConstructReplyFor(MethodCall method_call, object[] vals)
        {
            MethodReturn method_return = new MethodReturn(method_call.message.Header.Serial);
            Message      replyMsg      = method_return.message;

            Signature inSig = Signature.GetSig(vals);

            if (vals != null && vals.Length != 0)
            {
                MessageWriter writer = new MessageWriter(Connection.NativeEndianness);

                foreach (object arg in vals)
                {
                    writer.Write(arg.GetType(), arg);
                }

                replyMsg.Body = writer.ToArray();
            }

            //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
            if (method_call.Sender != null)
            {
                replyMsg.Header.Fields[FieldCode.Destination] = method_call.Sender;
            }

            replyMsg.Signature = inSig;

            //replyMsg.WriteHeader ();

            return(replyMsg);
        }
Ejemplo n.º 6
0
        //TODO: merge this with the above method
        public static Message ConstructReplyFor(MethodCall method_call, Type retType, object retVal)
        {
            MethodReturn method_return = new MethodReturn(method_call.message.Header.Serial);
            Message      replyMsg      = method_return.message;

            Signature inSig = Signature.GetSig(retType);

            if (inSig != Signature.Empty)
            {
                MessageWriter writer = new MessageWriter(Connection.NativeEndianness);
                writer.Write(retType, retVal);
                replyMsg.Body = writer.ToArray();
            }

            //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
            if (method_call.Sender != null)
            {
                replyMsg.Header.Fields[FieldCode.Destination] = method_call.Sender;
            }

            replyMsg.Signature = inSig;

            //replyMsg.WriteHeader ();

            return(replyMsg);
        }
Ejemplo n.º 7
0
		//TODO: clean up and get rid of reverse (or argIsOut) parm
		public void WriteArg (Type argType, string argName, bool argIsOut, bool reverse)
		{
			argType = argIsOut ? argType.GetElementType () : argType;
			if (argType == typeof (void))
				return;

			writer.WriteStartElement ("arg");

			if (!String.IsNullOrEmpty (argName))
				writer.WriteAttributeString ("name", argName);

			//we can't rely on the default direction (qt-dbus requires a direction at time of writing), so we use a boolean to reverse the parameter direction and make it explicit

			if (argIsOut)
				writer.WriteAttributeString ("direction", !reverse ? "out" : "in");
			else
				writer.WriteAttributeString ("direction", !reverse ? "in" : "out");

			Signature sig = Signature.GetSig (argType);

			//TODO: avoid writing null (DType.Invalid) to the XML stream
			writer.WriteAttributeString ("type", sig.Value);

			//annotations aren't valid in an arg element, so this is disabled
			//if (argType.IsEnum)
			//	WriteAnnotation ("org.ndesk.DBus.Enum", Mapper.GetInterfaceName (argType));

			writer.WriteEndElement ();
		}
        public void WriteVariant(Type type, object val)
        {
            Signature sig = Signature.GetSig(type);

            Write(sig);
            Write(type, val);
        }
Ejemplo n.º 9
0
        public override void HandleMethodCall(MethodCall method_call)
        {
            //object retVal = obj.GetType ().InvokeMember (method_call.Member, BindingFlags.InvokeMethod, null, obj, new object[0]);
            //IDynamicMetaObjectProvider idyn = obj as IDynamicMetaObjectProvider;

            object retVal = null;

            Exception raisedException = null;

            try {
                object[] args = MessageHelper.GetDynamicValues(method_call.message);
                retVal = ops.InvokeMember(obj, method_call.Member, args);
                //retVal = ops.Call (ops.GetMember (obj, method_call.Member), args);
            } catch (Exception e) {
                raisedException = e;
            }

            if (!method_call.message.ReplyExpected)
            {
                return;
            }

            Message msg      = method_call.message;
            Message replyMsg = null;

            if (raisedException == null)
            {
                MethodReturn method_return = new MethodReturn(msg.Header.Serial);
                replyMsg = method_return.message;
                if (retVal != null)
                {
                    if (retVal.GetType().FullName == "IronRuby.Builtins.MutableString")
                    {
                        retVal = retVal.ToString();
                    }
                    // TODO: Invalid sig handling
                    Signature     outSig    = Signature.GetSig(retVal.GetType());
                    MessageWriter retWriter = new MessageWriter();
                    retWriter.Write(retVal.GetType(), retVal);
                    //retWriter.WriteValueType (retVal, retVal.GetType ());
                    replyMsg.Body      = retWriter.ToArray();
                    replyMsg.Signature = outSig;
                }
            }
            else
            {
                Error 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);
        }
Ejemplo n.º 10
0
        public object ToType(Type conversionType, IFormatProvider provider)
        {
            Signature typeSig = Signature.GetSig(conversionType);

            if (typeSig != signature)
            {
                throw new InvalidCastException(String.Format("{0} doesn't match {1}", typeSig.ToString(), signature.ToString()));
            }

            MessageReader reader = new MessageReader(endianness, data);

            return(reader.ReadValue(conversionType));
        }
Ejemplo n.º 11
0
		//this is not in the spec, and is not finalized
		public void WriteEnum (Type type)
		{
			writer.WriteStartElement ("enum");
			writer.WriteAttributeString ("name", Mapper.GetInterfaceName (type));
			writer.WriteAttributeString ("type", Signature.GetSig (type.GetElementType ()).Value);
			writer.WriteAttributeString ("flags", (type.IsDefined (typeof (FlagsAttribute), false)) ? "true" : "false");

			string[] names = Enum.GetNames (type);

			int i = 0;
			foreach (Enum val in Enum.GetValues (type)) {
				writer.WriteStartElement ("element");
				writer.WriteAttributeString ("name", names[i++]);
				writer.WriteAttributeString ("value", val.ToString ("d"));
				writer.WriteEndElement ();
			}

			writer.WriteEndElement ();
		}
Ejemplo n.º 12
0
        public static bool SigsForMethod(MethodInfo mi, out Signature inSig, out Signature outSig)
        {
            inSig  = Signature.Empty;
            outSig = Signature.Empty;

            foreach (ParameterInfo parm in mi.GetParameters())
            {
                if (parm.IsOut)
                {
                    outSig += Signature.GetSig(parm.ParameterType.GetElementType());
                }
                else
                {
                    inSig += Signature.GetSig(parm.ParameterType);
                }
            }

            outSig += Signature.GetSig(mi.ReturnType);

            return(true);
        }
Ejemplo n.º 13
0
        public static Message ConstructDynamicReply(MethodCall method_call, MethodInfo mi, object retVal, object[] vals)
        {
            Type retType = mi.ReturnType;

            MethodReturn method_return = new MethodReturn(method_call.message.Header.Serial);
            Message      replyMsg      = method_return.message;

            Signature outSig = Signature.GetSig(retType);

            outSig += Signature.GetSig(Mapper.GetTypes(ArgDirection.Out, mi.GetParameters()));

            if (outSig != Signature.Empty)
            {
                MessageWriter writer = new MessageWriter(Connection.NativeEndianness);

                //first write the return value, if any
                if (retType != null && retType != typeof(void))
                {
                    writer.Write(retType, retVal);
                }

                //then write the out args
                WriteDynamicValues(writer, mi.GetParameters(), vals);

                replyMsg.Body = writer.ToArray();
            }

            //TODO: we should be more strict here, but this fallback was added as a quick fix for p2p
            if (method_call.Sender != null)
            {
                replyMsg.Header.Fields[FieldCode.Destination] = method_call.Sender;
            }

            replyMsg.Signature = outSig;

            return(replyMsg);
        }
Ejemplo n.º 14
0
        public bool CanConvertTo(Type conversionType)
        {
            Signature typeSig = Signature.GetSig(conversionType);

            return(signature == typeSig);
        }
Ejemplo n.º 15
0
        //this method walks the interface tree in an undefined manner and returns the first match, or if no matches are found, null
        //the logic needs review and cleanup
        //TODO: unify member name mapping as is already done with interfaces and args
        public static MethodInfo GetMethod(Type type, MethodCall method_call)
        {
            foreach (MemberInfo member in Mapper.GetPublicMembers(type))
            {
                //this could be made more efficient by using the given interface name earlier and avoiding walking through all public interfaces
                if (method_call.Interface != null)
                {
                    if (GetInterfaceName(member) != method_call.Interface)
                    {
                        continue;
                    }
                }

                MethodInfo meth    = null;
                Type[]     inTypes = null;

                if (member is PropertyInfo)
                {
                    PropertyInfo prop = member as PropertyInfo;

                    MethodInfo getter = prop.GetGetMethod(false);
                    MethodInfo setter = prop.GetSetMethod(false);

                    if (getter != null && "Get" + prop.Name == method_call.Member)
                    {
                        meth    = getter;
                        inTypes = Type.EmptyTypes;
                    }
                    else if (setter != null && "Set" + prop.Name == method_call.Member)
                    {
                        meth    = setter;
                        inTypes = new Type[] { prop.PropertyType };
                    }
                }
                else
                {
                    meth = member as MethodInfo;

                    if (meth == null)
                    {
                        continue;
                    }

                    if (meth.Name != method_call.Member)
                    {
                        continue;
                    }

                    inTypes = Mapper.GetTypes(ArgDirection.In, meth.GetParameters());
                }

                if (meth == null || inTypes == null)
                {
                    continue;
                }

                Signature inSig = Signature.GetSig(inTypes);

                if (inSig != method_call.Signature)
                {
                    continue;
                }

                return(meth);
            }

            return(null);
        }
Ejemplo n.º 16
0
 public HeaderTest(FieldCode field, object value)
 {
     Field     = field;
     Signature = Signature.GetSig(value.GetType());
     Value     = value;
 }
Ejemplo n.º 17
0
        public static void GenReadCollection(ILGenerator ilg, Type type)
        {
            //Console.WriteLine ("GenReadCollection " + type);
            //Console.WriteLine ("Sig: " + Signature.GetSig (type));
            int fixedSize = 0;

            if (type.IsArray && Signature.GetSig(type.GetElementType()).GetFixedSize(ref fixedSize))
            {
                GenReadArrayFixed(ilg, type, fixedSize);
                return;
            }

            LocalBuilder readerLocal = ilg.DeclareLocal(typeof(MessageReader));

            ilg.Emit(OpCodes.Stloc, readerLocal);

            //Type[] genArgs = type.GetGenericArguments ();
            Type[] genArgs = type.IsArray ? new Type[] { type.GetElementType() } : type.GetGenericArguments();
            //Type[] genArgs = new Type[] { type.GetElementType () };
            //Type tElem = genArgs[0];

            //Type collType = Mapper.GetGenericType (typeof (List<>), genArgs);
            Type collType = Mapper.GetGenericType(genArgs.Length == 2 ? typeof(Dictionary <,>) : typeof(List <>), genArgs);

            ConstructorInfo ctor = collType.GetConstructor(Type.EmptyTypes);

            ilg.Emit(OpCodes.Newobj, ctor);

            LocalBuilder collLocal = ilg.DeclareLocal(collType);

            ilg.Emit(OpCodes.Stloc, collLocal);

            //MethodInfo addMethod = dictType.GetMethod ("Add", new Type[] { tKey, tValue });
            MethodInfo addMethod = collType.GetMethod("Add", genArgs);


            // Read the array's byte length
            MethodInfo readUInt32Method = GetReadMethod(typeof(uint));

            ilg.Emit(OpCodes.Ldloc, readerLocal);
            ilg.Emit(readUInt32Method.IsFinal ? OpCodes.Call : OpCodes.Callvirt, readUInt32Method);

            {
                // Align to 8 for structs
                ilg.Emit(OpCodes.Ldloc, readerLocal);
                //ilg.Emit (OpCodes.Ldc_I4, 8);
                // TODO: This padding logic is sketchy
                ilg.Emit(OpCodes.Ldc_I4, genArgs.Length > 1 ? 8 : Signature.GetSig(genArgs[0]).Alignment);
                ilg.Emit(OpCodes.Call, messageReaderReadPad);
            }

            // Similar to the fixed array loop code

            FieldInfo    posField    = typeof(MessageReader).GetField("pos");
            LocalBuilder endPosLocal = ilg.DeclareLocal(typeof(int));

            ilg.Emit(OpCodes.Ldloc, readerLocal);
            ilg.Emit(OpCodes.Ldfld, posField);

            // Add the current position and byte length to determine endPos
            // TODO: Consider padding?
            ilg.Emit(OpCodes.Add);
            ilg.Emit(OpCodes.Stloc, endPosLocal);

            {
                Label loopStartLabel = ilg.DefineLabel();
                Label loopEndLabel   = ilg.DefineLabel();

                ilg.Emit(OpCodes.Br, loopEndLabel);

                ilg.MarkLabel(loopStartLabel);

                {
                    if (genArgs.Length > 1)
                    {
                        // Align to 8 for structs
                        ilg.Emit(OpCodes.Ldloc, readerLocal);
                        ilg.Emit(OpCodes.Ldc_I4, 8);
                        ilg.Emit(OpCodes.Call, messageReaderReadPad);
                    }

                    // Read and store an element to the array
                    var lbList = new List <LocalBuilder>();
                    foreach (Type genArg in genArgs)
                    {
                        ilg.Emit(OpCodes.Ldloc, readerLocal);
                        var lb = ilg.DeclareLocal(genArg);
                        lbList.Add(lb);
                        GenReader(ilg, genArg);
                        ilg.Emit(OpCodes.Stloc, lb);
                    }

                    ilg.Emit(OpCodes.Ldloc, collLocal);
                    foreach (var l in lbList)
                    {
                        ilg.Emit(OpCodes.Ldloc, l);
                    }
                    ilg.Emit(OpCodes.Call, addMethod);
                }

                ilg.MarkLabel(loopEndLabel);

                //ilg.Emit (OpCodes.Ldloc, indexLocal);
                ilg.Emit(OpCodes.Ldloc, readerLocal);
                ilg.Emit(OpCodes.Ldfld, posField);

                ilg.Emit(OpCodes.Ldloc, endPosLocal);
                ilg.Emit(OpCodes.Blt, loopStartLabel);
            }

            // Return the new collection
            ilg.Emit(OpCodes.Ldloc, collLocal);

            if (type.IsArray)
            {
                MethodInfo toArrayMethod = collType.GetMethod("ToArray", Type.EmptyTypes);
                ilg.Emit(OpCodes.Call, toArrayMethod);
            }
        }
Ejemplo n.º 18
0
        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];

                MatchRule rule = new MatchRule();
                rule.MessageType = MessageType.Signal;
                rule.Interface   = Mapper.GetInterfaceName(mi);
                rule.Member      = ename;
                rule.Path        = object_path;

                if (parts[0] == "add")
                {
                    if (conn.Handlers.ContainsKey(rule))
                    {
                        conn.Handlers[rule] = Delegate.Combine(conn.Handlers[rule], dlg);
                    }
                    else
                    {
                        conn.Handlers[rule] = dlg;
                        conn.AddMatch(rule.ToString());
                    }
                }
                else if (parts[0] == "remove")
                {
                    conn.Handlers[rule] = Delegate.Remove(conn.Handlers[rule], dlg);
                    if (conn.Handlers[rule] == null)
                    {
                        conn.RemoveMatch(rule.ToString());
                        conn.Handlers.Remove(rule);
                    }
                }
                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);
                    reader.GetValue(out errMsg);
                }
                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;
        }
Ejemplo n.º 19
0
        public static void GenReadArrayFixed(ILGenerator ilg, Type t, int knownElemSize)
        {
            //Console.Error.WriteLine ("GenReadArrayFixed " + t);
            LocalBuilder readerLocal = ilg.DeclareLocal(typeof(MessageReader));

            ilg.Emit(OpCodes.Stloc, readerLocal);

            Type      tElem               = t.GetElementType();
            Signature sigElem             = Signature.GetSig(tElem);
            int       alignElem           = sigElem.Alignment;
            int       knownElemSizePadded = Protocol.Padded(knownElemSize, sigElem.Alignment);
            Type      tUnder              = tElem.IsEnum ? Enum.GetUnderlyingType(tElem) : tElem;
            int       managedElemSize     = System.Runtime.InteropServices.Marshal.SizeOf(tUnder);

            /*
             * Console.WriteLine ("managedElemSize: " + managedElemSize);
             * Console.WriteLine ("elemSize: " + knownElemSize);
             * Console.WriteLine ("elemSizePadded: " + knownElemSizePadded);
             */

            // Read the array's byte length
            ilg.Emit(OpCodes.Ldloc, readerLocal);
            MethodInfo exactMethod = GetReadMethod(typeof(uint));

            ilg.Emit(exactMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, exactMethod);
            LocalBuilder sizeLocal = ilg.DeclareLocal(typeof(uint));

            ilg.Emit(OpCodes.Stloc, sizeLocal);

            /*
             * // Take the array's byte length
             * ilg.Emit (OpCodes.Ldloc, sizeLocal);
             * // Divide by the known element size
             * //ilg.Emit (OpCodes.Ldc_I4, knownElemSizePadded);
             * ilg.Emit (OpCodes.Ldc_I4, knownElemSize);
             * ilg.Emit (OpCodes.Div_Un);
             */

            // Create a new array of the correct element length
            ilg.Emit(OpCodes.Ldloc, sizeLocal);
            if (knownElemSizePadded > 1)
            {
                ilg.Emit(OpCodes.Ldc_I4, alignElem);
                MethodInfo paddedMethod = typeof(Protocol).GetMethod("Padded");
                ilg.Emit(OpCodes.Call, paddedMethod);
                // Divide by the known element size
                ilg.Emit(OpCodes.Ldc_I4, knownElemSizePadded);
                ilg.Emit(OpCodes.Div_Un);
            }
            ilg.Emit(OpCodes.Newarr, tElem);
            LocalBuilder aryLocal = ilg.DeclareLocal(t);

            ilg.Emit(OpCodes.Stloc, aryLocal);

            Label nonBlitLabel = ilg.DefineLabel();
            Label endLabel     = ilg.DefineLabel();

            // Skip read or blit for zero-length arrays.
            ilg.Emit(OpCodes.Ldloc, sizeLocal);
            ilg.Emit(OpCodes.Brfalse, endLabel);

            // WARNING: This may skew pos when we later increment it!
            if (alignElem > 4)
            {
                // Align to element if alignment requirement is higher than 4 (since we just read a uint)
                ilg.Emit(OpCodes.Ldloc, readerLocal);
                ilg.Emit(OpCodes.Ldc_I4, alignElem);
                ilg.Emit(OpCodes.Call, messageReaderReadPad);
            }

            // Blit where possible

            // shouldBlit: Blit if endian is native
            // mustBlit: Blit regardless of endian (ie. byte or structs containing only bytes)

            bool shouldBlit = tElem.IsValueType && knownElemSizePadded == managedElemSize && !sigElem.IsStruct;

            //bool shouldBlit = tElem.IsValueType && knownElemSizePadded == managedElemSize;

            // bool and char are not reliably blittable, so we don't allow blitting in these cases.
            // Their exact layout varies between runtimes, platforms and even data types.
            shouldBlit &= tElem != typeof(bool) && tElem != typeof(char);

            bool mustBlit = shouldBlit && knownElemSizePadded == 1;

            if (shouldBlit)
            {
                //Console.Error.WriteLine ("Blit read array " + tElem);

                if (!mustBlit)
                {
                    // Check to see if we can blit the data structures
                    FieldInfo nativeEndianField = typeof(MessageReader).GetField("IsNativeEndian");
                    ilg.Emit(OpCodes.Ldloc, readerLocal);
                    ilg.Emit(OpCodes.Ldfld, nativeEndianField);
                    ilg.Emit(OpCodes.Brfalse_S, nonBlitLabel);
                }

                // Get the destination address
                ilg.Emit(OpCodes.Ldloc, aryLocal);
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ldelema, tElem);

                // Get the source address
                FieldInfo dataField = typeof(MessageReader).GetField("data");
                FieldInfo posField  = typeof(MessageReader).GetField("pos");
                ilg.Emit(OpCodes.Ldloc, readerLocal);
                ilg.Emit(OpCodes.Ldfld, dataField);
                {
                    ilg.Emit(OpCodes.Ldloc, readerLocal);
                    ilg.Emit(OpCodes.Ldfld, posField);
                }
                ilg.Emit(OpCodes.Ldelema, typeof(byte));

                // The number of bytes to copy
                ilg.Emit(OpCodes.Ldloc, sizeLocal);

                // Blit the array
                ilg.Emit(OpCodes.Cpblk);

                // pos += bytesRead
                ilg.Emit(OpCodes.Ldloc, readerLocal);
                ilg.Emit(OpCodes.Ldloc, readerLocal);
                ilg.Emit(OpCodes.Ldfld, posField);
                ilg.Emit(OpCodes.Ldloc, sizeLocal);
                ilg.Emit(OpCodes.Add);
                ilg.Emit(OpCodes.Stfld, posField);

                ilg.Emit(OpCodes.Br, endLabel);
            }

            if (!mustBlit)
            {
                ilg.MarkLabel(nonBlitLabel);

                // for (int i = 0 ; i < ary.Length ; i++)
                LocalBuilder indexLocal = ilg.DeclareLocal(typeof(int));
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Stloc, indexLocal);

                Label loopStartLabel = ilg.DefineLabel();
                Label loopEndLabel   = ilg.DefineLabel();

                ilg.Emit(OpCodes.Br, loopEndLabel);

                ilg.MarkLabel(loopStartLabel);

                {
                    // Read and store an element to the array
                    ilg.Emit(OpCodes.Ldloc, aryLocal);
                    ilg.Emit(OpCodes.Ldloc, indexLocal);

                    ilg.Emit(OpCodes.Ldloc, readerLocal);
                    GenReader(ilg, tElem);

                    ilg.Emit(OpCodes.Stelem, tElem);
                }

                // i++
                ilg.Emit(OpCodes.Ldloc, indexLocal);
                ilg.Emit(OpCodes.Ldc_I4_1);
                ilg.Emit(OpCodes.Add);
                ilg.Emit(OpCodes.Stloc, indexLocal);

                ilg.MarkLabel(loopEndLabel);
                ilg.Emit(OpCodes.Ldloc, indexLocal);
                ilg.Emit(OpCodes.Ldloc, aryLocal);
                ilg.Emit(OpCodes.Ldlen);
                ilg.Emit(OpCodes.Blt, loopStartLabel);
            }

            ilg.MarkLabel(endLabel);

            // Return the new array
            ilg.Emit(OpCodes.Ldloc, aryLocal);
        }
Ejemplo n.º 20
0
        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);
        }
Ejemplo n.º 21
0
        public static void GenHookupMethod(ILGenerator ilg, MethodInfo declMethod, MethodInfo invokeMethod, string @interface, string member)
        {
            ParameterInfo[] parms   = declMethod.GetParameters();
            Type            retType = declMethod.ReturnType;

            //the BusObject instance
            ilg.Emit(OpCodes.Ldarg_0);

            //MethodInfo

            /*
             * ilg.Emit (OpCodes.Ldtoken, declMethod);
             * ilg.Emit (OpCodes.Call, getMethodFromHandleMethod);
             */

            //interface
            ilg.Emit(OpCodes.Ldstr, @interface);

            //special case event add/remove methods
            if (declMethod.IsSpecialName && (declMethod.Name.StartsWith("add_") || declMethod.Name.StartsWith("remove_")))
            {
                string[] parts = declMethod.Name.Split(new char[] { '_' }, 2);
                string   ename = parts[1];
                //Delegate dlg = (Delegate)inArgs[0];
                bool adding = parts[0] == "add";

                ilg.Emit(OpCodes.Ldstr, ename);

                ilg.Emit(OpCodes.Ldarg_1);

                ilg.Emit(OpCodes.Ldc_I4, adding ? 1 : 0);

                ilg.Emit(OpCodes.Tailcall);
                ilg.Emit(toggleSignalMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, toggleSignalMethod);
                ilg.Emit(OpCodes.Ret);
                return;
            }

            //property accessor mapping
            if (declMethod.IsSpecialName)
            {
                if (member.StartsWith("get_"))
                {
                    member = "Get" + member.Substring(4);
                }
                else if (member.StartsWith("set_"))
                {
                    member = "Set" + member.Substring(4);
                }
            }

            //member
            ilg.Emit(OpCodes.Ldstr, member);

            //signature
            Signature inSig  = Signature.Empty;
            Signature outSig = Signature.Empty;

            if (!declMethod.IsSpecialName)
            {
                foreach (ParameterInfo parm in parms)
                {
                    if (parm.IsOut)
                    {
                        outSig += Signature.GetSig(parm.ParameterType.GetElementType());
                    }
                    else
                    {
                        inSig += Signature.GetSig(parm.ParameterType);
                    }
                }
            }

            ilg.Emit(OpCodes.Ldstr, inSig.Value);

            LocalBuilder writer = ilg.DeclareLocal(typeof(MessageWriter));

            ilg.Emit(OpCodes.Newobj, messageWriterConstructor);
            ilg.Emit(OpCodes.Stloc, writer);

            foreach (ParameterInfo parm in parms)
            {
                if (parm.IsOut)
                {
                    continue;
                }

                Type t = parm.ParameterType;
                //offset by one to account for "this"
                int i = parm.Position + 1;

                //null checking of parameters (but not their recursive contents)
                if (!t.IsValueType)
                {
                    Label notNull = ilg.DefineLabel();

                    //if the value is null...
                    ilg.Emit(OpCodes.Ldarg, i);
                    ilg.Emit(OpCodes.Brtrue_S, notNull);

                    //...throw Exception
                    string paramName = parm.Name;
                    ilg.Emit(OpCodes.Ldstr, paramName);
                    ilg.Emit(OpCodes.Newobj, argumentNullExceptionConstructor);
                    ilg.Emit(OpCodes.Throw);

                    //was not null, so all is well
                    ilg.MarkLabel(notNull);
                }

                ilg.Emit(OpCodes.Ldloc, writer);

                //the parameter
                ilg.Emit(OpCodes.Ldarg, i);

                GenWriter(ilg, t);
            }

            ilg.Emit(OpCodes.Ldloc, writer);

            //the expected return Type
            ilg.Emit(OpCodes.Ldtoken, retType);
            ilg.Emit(OpCodes.Call, getTypeFromHandleMethod);

            LocalBuilder exc = ilg.DeclareLocal(typeof(Exception));

            ilg.Emit(OpCodes.Ldloca_S, exc);

            //make the call
            ilg.Emit(invokeMethod.IsFinal ? OpCodes.Call : OpCodes.Callvirt, invokeMethod);

            //define a label we'll use to deal with a non-null Exception
            Label noErr = ilg.DefineLabel();

            //if the out Exception is not null...
            ilg.Emit(OpCodes.Ldloc, exc);
            ilg.Emit(OpCodes.Brfalse_S, noErr);

            //...throw it.
            ilg.Emit(OpCodes.Ldloc, exc);
            ilg.Emit(OpCodes.Throw);

            //Exception was null, so all is well
            ilg.MarkLabel(noErr);

            if (retType == typeof(void))
            {
                //we aren't expecting a return value, so throw away the (hopefully) null return
                if (invokeMethod.ReturnType != typeof(void))
                {
                    ilg.Emit(OpCodes.Pop);
                }
            }
            else
            {
                if (retType.IsValueType)
                {
                    ilg.Emit(OpCodes.Unbox_Any, retType);
                }
                else
                {
                    ilg.Emit(OpCodes.Castclass, retType);
                }
            }

            ilg.Emit(OpCodes.Ret);
        }
Ejemplo n.º 22
0
        //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;
        }
Ejemplo n.º 23
0
 public static string GetSignatureString(Type type)
 {
     return(Signature.GetSig(type).Value);
 }