/// <summary> /// Write a <see cref="IpcMessage"/> to the network /// </summary> /// <param name="msg">Message to write</param> public void WriteMessage(IpcMessage msg) { // serialize DataContractSerializer serializer = new DataContractSerializer(typeof(IpcMessage), KnownTypes); using (MemoryStream stream = new MemoryStream()) { XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream); serializer.WriteObject(writer, msg); writer.Flush(); byte[] binaryMsg = stream.ToArray(); // encrypt message if (encrypted) { if (Encryptor == null) { throw new NullReferenceException("Encryption requested while no encryptor was set"); } else { binaryMsg = Encryptor.EncryptMessage(binaryMsg); } } // write the raw message this.WriteBytes(binaryMsg); } // switch on encryption if (msg.StatusMsg == StatusMessage.Encrypt) { encrypted = true; } }
/// <summary> /// Process a received message by calling the corresponding method on the service instance and /// returning the return value over the network. /// </summary> /// <param name="stream">The message stream</param> /// <param name="streamId">A GUID identifying this connection</param> public bool ProcessMessage(IpcStream stream, Guid streamId) { IpcMessage msg = stream.ReadMessage(); // this was a close-connection notification if (msg.StatusMsg == StatusMessage.CloseConnection) { return(false); } // or this is just a keepalive ping else if (msg.StatusMsg == StatusMessage.Ping) { return(true); } bool processedOk = false; string error = ""; object rv = null; IpcMessage returnMsg = new IpcMessage(); // find the service if (services.TryGetValue(msg.Service, out object instance) && instance != null) { // double check method existence against type-list for security // typelist will contain interfaces instead of instances if (types[msg.Service].GetMethod(msg.Method) != null) { // separate handling for stateful service if (instance is StatefulProxy) { try { // invoke method System.Reflection.MethodInfo method = (instance as StatefulProxy).Type.GetMethod(msg.Method); if (method == null) { throw new InvalidOperationException("Method not found in stateful proxy"); } rv = (instance as StatefulProxy).Invoke(streamId, method, msg.Parameters); processedOk = true; // check if encryption is required if (Attribute.IsDefined(method, typeof(EncryptIfTrueAttribute)) && (bool)rv == true) { returnMsg.StatusMsg = StatusMessage.Encrypt; } } catch (Exception e) { error = e.ToString(); } } else { // get the method System.Reflection.MethodInfo method = instance.GetType().GetMethod(msg.Method); if (method != null) { try { // invoke method rv = method.Invoke(instance, msg.Parameters); processedOk = true; // check if encryption is required if (Attribute.IsDefined(method, typeof(EncryptIfTrueAttribute)) && (bool)rv == true) { returnMsg.StatusMsg = StatusMessage.Encrypt; } } catch (Exception e) { error = e.ToString(); } } else { error = "Could not find method"; } } } else { error = "Could not find method in type"; } } else { error = "Could not find service"; } // return either return value or error message if (processedOk) { returnMsg.Return = rv; } else { returnMsg.Error = error; returnMsg.StatusMsg = StatusMessage.None; } stream.WriteMessage(returnMsg); // if there's more to come, keep reading a next message if (msg.StatusMsg == StatusMessage.KeepAlive) { return(true); } else // otherwise close the connection { return(false); } }