public 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 MethodInfo mi = Mapper.GetMethod (type, method_call); if (mi == null) { conn.MaybeSendUnknownMethodError (method_call); return; } object retObj = null; try { object[] inArgs = MessageHelper.GetDynamicValues (method_call.message, mi.GetParameters ()); retObj = mi.Invoke (obj, inArgs); } catch (TargetInvocationException e) { if (!method_call.message.ReplyExpected) return; Exception ie = e.InnerException; //TODO: complete exception sending support Error error = new Error (Mapper.GetInterfaceName (ie.GetType ()), method_call.message.Header.Serial); error.message.Signature = new Signature (DType.String); MessageWriter writer = new MessageWriter (Connection.NativeEndianness); writer.connection = conn; writer.Write (ie.Message); error.message.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) error.message.Header.Fields[FieldCode.Destination] = method_call.Sender; conn.Send (error.message); return; } if (method_call.message.ReplyExpected) { /* object[] retObjs; if (retObj == null) { retObjs = new object[0]; } else { retObjs = new object[1]; retObjs[0] = retObj; } Message reply = ConstructReplyFor (method_call, retObjs); */ Message reply = MessageHelper.ConstructReplyFor (method_call, mi.ReturnType, retObj); conn.Send (reply); } }
public Error CreateError(string errorName, string errorMessage) { Error error = new Error(errorName, message.Header.Serial); error.message.Signature = Signature.StringSig; MessageWriter writer = new MessageWriter(message.Header.Endianness); //writer.connection = conn; writer.Write(errorMessage); error.message.Body = writer.ToArray(); //if (method_call.Sender != null) // replyMsg.Header[FieldCode.Destination] = method_call.Sender; return(error); }
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); }
public void GetHeaderDataToStream(Stream stream) { if (Body != null) { Header.Length = (uint)Body.Length; } MessageWriter writer = new MessageWriter(Header.Endianness); //headerWriter (writer, Header); writer.Write((byte)Header.Endianness); writer.Write((byte)Header.MessageType); writer.Write((byte)Header.Flags); writer.Write(Header.MajorVersion); writer.Write(Header.Length); writer.Write(Header.Serial); writer.WriteHeaderFields(Header.Fields); writer.CloseWrite(); writer.ToStream(stream); }
//public HeaderField[] Fields; /* * public void SetHeaderData (byte[] data) * { * EndianFlag endianness = (EndianFlag)data[0]; * MessageReader reader = new MessageReader (endianness, data); * * Header = (Header)reader.ReadStruct (typeof (Header)); * } */ //TypeWriter<Header> headerWriter = TypeImplementer.GetTypeWriter<Header> (); public byte[] GetHeaderData() { if (Body != null) { Header.Length = (uint)Body.Length; } MessageWriter writer = new MessageWriter(Header.Endianness); //writer.stream.Capacity = 512; //headerWriter (writer, Header); writer.Write((byte)Header.Endianness); writer.Write((byte)Header.MessageType); writer.Write((byte)Header.Flags); writer.Write(Header.MajorVersion); writer.Write(Header.Length); writer.Write(Header.Serial); writer.WriteHeaderFields(Header.Fields); writer.CloseWrite(); return(writer.ToArray()); }
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; }
public static Message ConstructReply (MethodCall method_call, params 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; }
public static void WriteDynamicValues (MessageWriter mw, ParameterInfo[] parms, object[] vals) { foreach (ParameterInfo parm in parms) { if (!parm.IsOut) continue; Type actualType = parm.ParameterType.GetElementType (); mw.Write (actualType, vals[parm.Position]); } }
public static Message CreateUnknownMethodError (MethodCall method_call) { if (!method_call.message.ReplyExpected) return null; string errMsg = String.Format ("Method \"{0}\" with signature \"{1}\" on interface \"{2}\" doesn't exist", method_call.Member, method_call.Signature.Value, method_call.Interface); Error error = new Error ("org.freedesktop.DBus.Error.UnknownMethod", method_call.message.Header.Serial); error.message.Signature = new Signature (DType.String); MessageWriter writer = new MessageWriter (Connection.NativeEndianness); writer.Write (errMsg); error.message.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) error.message.Header.Fields[FieldCode.Destination] = method_call.Sender; return error.message; }
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; }
public void GetHeaderDataToStream(Stream stream) { if (Body != null) Header.Length = (uint)Body.Length; MessageWriter writer = new MessageWriter (Header.Endianness); //headerWriter (writer, Header); writer.Write ((byte)Header.Endianness); writer.Write ((byte)Header.MessageType); writer.Write ((byte)Header.Flags); writer.Write (Header.MajorVersion); writer.Write (Header.Length); writer.Write (Header.Serial); writer.WriteHeaderFields (Header.Fields); writer.CloseWrite (); writer.ToStream (stream); }
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); }
public 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 MethodInfo mi = Mapper.GetMethod(type, method_call); if (mi == null) { conn.MaybeSendUnknownMethodError(method_call); return; } object retObj = null; try { object[] inArgs = MessageHelper.GetDynamicValues(method_call.message, mi.GetParameters()); retObj = mi.Invoke(obj, inArgs); } catch (TargetInvocationException e) { if (!method_call.message.ReplyExpected) { return; } Exception ie = e.InnerException; //TODO: complete exception sending support Error error = new Error(Mapper.GetInterfaceName(ie.GetType()), method_call.message.Header.Serial); error.message.Signature = new Signature(DType.String); MessageWriter writer = new MessageWriter(Connection.NativeEndianness); writer.connection = conn; writer.Write(ie.Message); error.message.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) { error.message.Header.Fields[FieldCode.Destination] = method_call.Sender; } conn.Send(error.message); return; } if (method_call.message.ReplyExpected) { /* * object[] retObjs; * * if (retObj == null) { * retObjs = new object[0]; * } else { * retObjs = new object[1]; * retObjs[0] = retObj; * } * * Message reply = ConstructReplyFor (method_call, retObjs); */ Message reply = MessageHelper.ConstructReplyFor(method_call, mi.ReturnType, retObj); conn.Send(reply); } }
//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; }
public Error CreateError(string errorName, string errorMessage) { Error error = new Error (errorName, message.Header.Serial); error.message.Signature = Signature.StringSig; MessageWriter writer = new MessageWriter (message.Header.Endianness); //writer.connection = conn; writer.Write (errorMessage); error.message.Body = writer.ToArray (); //if (method_call.Sender != null) // replyMsg.Header[FieldCode.Destination] = method_call.Sender; return error; }
void RaiseNameSignal(string memberSuffix, string name) { // Name* signals on org.freedesktop.DBus are connection-specific. // We handle them here as a special case. Signal nameSignal = new Signal (Path, DBusInterface, "Name" + memberSuffix); MessageWriter mw = new MessageWriter (); mw.Write (name); nameSignal.message.Body = mw.ToArray (); nameSignal.message.Signature = Signature.StringSig; Caller.Send (nameSignal.message); }
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; }
//public HeaderField[] Fields; /* public void SetHeaderData (byte[] data) { EndianFlag endianness = (EndianFlag)data[0]; MessageReader reader = new MessageReader (endianness, data); Header = (Header)reader.ReadStruct (typeof (Header)); } */ //TypeWriter<Header> headerWriter = TypeImplementer.GetTypeWriter<Header> (); public byte[] GetHeaderData() { if (Body != null) Header.Length = (uint)Body.Length; MessageWriter writer = new MessageWriter (Header.Endianness); //writer.stream.Capacity = 512; //headerWriter (writer, Header); writer.Write ((byte)Header.Endianness); writer.Write ((byte)Header.MessageType); writer.Write ((byte)Header.Flags); writer.Write (Header.MajorVersion); writer.Write (Header.Length); writer.Write (Header.Serial); writer.WriteHeaderFields (Header.Fields); writer.CloseWrite (); return writer.ToArray (); }