Ejemplo n.º 1
0
        public async Task LocalStart(IGenerateProxies proxyGenerator, ConstructorInfo ctor, bool hostInstance, params object[] arguments)
        {
            Instance = await this.LocalStart(disposeToken, proxyGenerator, ctor, hostInstance, arguments).ConfigureAwait(false);

            IsHost = hostInstance;

            this.StartListening(disposeToken, remoteRequests);
        }
Ejemplo n.º 2
0
        public async Task RemoteStart(IGenerateProxies proxyGenerator)
        {
            var(isHost, instance) = await this.RemoteStart(disposeToken, proxyGenerator).ConfigureAwait(false);

            IsHost   = isHost;
            Instance = instance;

            this.StartListening(disposeToken, remoteRequests);
        }
 internal TestConnection(bool isParent, IAmASerializer serializer, IGenerateProxies proxyGenerator, Stream reader, Stream writer)
     : base(isParent, serializer, proxyGenerator, reader, writer)
 {
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates a child domain.
        /// </summary>
        public ChildDomain AddChildDomain(ProcessStartInfo startInfo, IAmASerializer serializer = null, IGenerateProxies proxyGenerator = null)
        {
            //if the path is missing then
            if (startInfo == null)
            {
                throw new ArgumentNullException(nameof(startInfo));
            }

            var childProcess = new Process
            {
                StartInfo = startInfo
            };

            proxyGenerator = proxyGenerator ?? DefaultProxyFactory.Instance;
            serializer     = serializer ?? DefaultSerializer.Instance;

            var debuggerEnabled = Debugger.IsAttached && DebuggingSupported;

            var read  = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
            var write = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);

            startInfo.Environment[connectionStringVarName] =
                $"pid={Current.Process.Id}&" +
                $"write={write.GetClientHandleAsString()}&" +
                $"read={read.GetClientHandleAsString()}&" +
                $"debug={(debuggerEnabled ? 1 : 0)}&" +
                $"serializer={HttpUtility.UrlEncode(serializer.Name)}&" +
                $"proxyGenerator={HttpUtility.UrlEncode(proxyGenerator.Name)}";
            startInfo.UseShellExecute = false;

            childProcess.EnableRaisingEvents = true;

            childProcess.Start();

            read.DisposeLocalCopyOfClientHandle();
            write.DisposeLocalCopyOfClientHandle();

            if (debuggerEnabled)
            {
                if (!TryToAttachDebugger(childProcess.Id))
                {
                    debuggerEnabled = false;
                }

                //signal to the child process to continue now that the debugger is attached
                read.Write(new byte[1], 0, 1);
            }

            //NOTE: the read and write streams are switched for the server side
            var child = new ChildDomain(childProcess, debuggerEnabled, new Connection(this, serializer, proxyGenerator, write, read));

            children[childProcess.Id] = child;

            child.Process.Exited += (sender, eventArgs) => children.TryRemove(childProcess.Id, out _);

            if (child.Process.HasExited)
            {
                children.TryRemove(childProcess.Id, out _);
            }

            return(child);
        }
 public Task LocalStart(IGenerateProxies proxyGenerator, ConstructorInfo ctor, bool hostInstance, params object[] arguments)
 {
     IsHost = hostInstance;
     Connection.Write(Id, new MemoryStream(InitBytes.ToByteArray(), false));
     return(Task.CompletedTask);
 }
 public Task RemoteStart(IGenerateProxies proxyGenerator)
 {
     IsHost = false;
     return(Task.CompletedTask);
 }
Ejemplo n.º 7
0
        public static async Task <(bool isHost, object instance)> RemoteStart(this IInternalChannel channel, CancellationTokenSource cancel, IGenerateProxies proxyGenerator)
        {
            if (channel == null)
            {
                throw new ArgumentNullException(nameof(channel));
            }

            if (cancel == null)
            {
                throw new ArgumentNullException(nameof(cancel));
            }

            if (proxyGenerator == null)
            {
                throw new ArgumentNullException(nameof(proxyGenerator));
            }

            bool   isHost;
            object instance;
            var    responseStream = new MemoryStream();

            using (var writer = new BinaryWriter(responseStream, Encoding.UTF8, true))
            {
                try
                {
                    //write success (we may rewrite this byte if there is an error later)
                    writer.Write(true);

                    //read hostInstance
                    var makeProxy = channel.Reader.ReadBoolean();
                    isHost = !makeProxy;

                    //read type to proxy
                    var type = (Type)await channel.Serializer.Deserialize(channel.Reader, typeof(Type), channel.Connection, cancel.Token).ConfigureAwait(false);

                    //read ctor param count
                    var paramCount = channel.Reader.ReadByte();

                    //read each ctor param in pairs of type and value
                    var arguments = new object[paramCount];
                    var types     = new Type[paramCount];
                    for (var index = 0; index < paramCount; index++)
                    {
                        var paramType = types[index] = (Type)await channel.Serializer.Deserialize(channel.Reader, typeof(Type), channel.Connection, cancel.Token).ConfigureAwait(false);

                        arguments[index] = await channel.Serializer.Deserialize(channel.Reader, paramType, channel.Connection, cancel.Token).ConfigureAwait(false);
                    }

                    //find the ctor
                    var ctor = type.GetConstructors()
                               .Select(item => new
                    {
                        ctor    = item,
                        @params = item.GetParameters()
                    })
                               .FirstOrDefault(ctorInfo =>
                                               [email protected] == paramCount &&
                                               ctorInfo.@params
                                               .Select(param => param.ParameterType)
                                               .Zip(types, (a, b) => a.IsAssignableFrom(b))
                                               .All(result => result))?.ctor ??
                               throw new ArgumentException("Unable fond the constructor.");

                    //create the instance
                    instance = makeProxy ? proxyGenerator.GenerateProxy(channel, ctor, arguments) : ctor.Invoke(arguments);
                }
                catch (Exception error)
                {
                    instance = null;
                    isHost   = false;
                    responseStream.Position = 0;
                    responseStream.SetLength(0);

                    var errorType = error.GetType();

                    //write unsuccessful
                    writer.Write(false);

                    //write the error
                    await channel.Serializer.Serialize(writer, typeof(Type), errorType, channel.Connection).ConfigureAwait(false);

                    await channel.Serializer.Serialize(writer, errorType, error, channel.Connection).ConfigureAwait(false);
                }
            }

            //send the response
            try
            {
                responseStream.Position = 0;
                channel.Connection.Write(channel.Id, responseStream);
            }
            catch
            {
                // ignored
            }

            return(isHost, instance);
        }
Ejemplo n.º 8
0
 public static Task <object> LocalStart(this IInternalChannel channel, CancellationTokenSource cancel, IGenerateProxies proxyGenerator, ConstructorInfo ctor, bool hostInstance, params object[] arguments) =>
 channel.localStart(cancel, proxyGenerator, ctor, hostInstance, null, arguments);
Ejemplo n.º 9
0
        private static async Task <object> localStart(this IInternalChannel channel, CancellationTokenSource cancel, IGenerateProxies proxyGenerator, ConstructorInfo ctor, bool hostInstance, object instance, params object[] arguments)
        {
            if (channel == null)
            {
                throw new ArgumentNullException(nameof(channel));
            }

            if (cancel == null)
            {
                throw new ArgumentNullException(nameof(cancel));
            }

            if (ctor == null)
            {
                throw new ArgumentNullException(nameof(ctor));
            }

            if (arguments == null)
            {
                throw new ArgumentNullException(nameof(arguments));
            }

            if (!(proxyGenerator == null ^ instance == null))
            {
                throw new InvalidOperationException($"Only one instance of {nameof(proxyGenerator)} or {nameof(instance)} is allowed.");
            }

            if (instance != null && !hostInstance)
            {
                throw new InvalidOperationException("Instance must be hosted.");
            }

            var response     = new byte[] { 1 };
            var responseTask = channel.Buffer.ReadAsync(response, 0, 1);

            var initRequest = new MemoryStream();

            using (var writer = new BinaryWriter(initRequest, Encoding.UTF8, true))
            {
                //write hostInstance
                writer.Write(hostInstance);

                //write type to proxy
                await channel.Serializer.Serialize(writer, typeof(Type), ctor.DeclaringType, channel.Connection).ConfigureAwait(false);

                //write ctor param count
                var @params = ctor.GetParameters();
                writer.Write((byte)@params.Length);

                if (arguments.Length != @params.Length)
                {
                    throw new ArgumentException("Invalid constructor.");
                }

                //write each ctor param in pairs of type and value
                foreach (var param in @params.Zip(arguments, (param, arg) => new { type = arg?.GetType() ?? param.ParameterType, arg }))
                {
                    await channel.Serializer.Serialize(writer, typeof(Type), param.type, channel.Connection).ConfigureAwait(false);

                    await channel.Serializer.Serialize(writer, param.type, param.arg, channel.Connection).ConfigureAwait(false);
                }
            }

            initRequest.Position = 0;
            channel.Connection.Write(channel.Id, initRequest);

            await responseTask.ConfigureAwait(false);

            if (response[0] != 0)
            {
                return(hostInstance ? instance ?? ctor.Invoke(arguments) : proxyGenerator.GenerateProxy(channel, ctor, arguments));
            }

            var exceptionType = (Type)await channel.Serializer.Deserialize(channel.Reader, typeof(Type), channel.Connection, cancel.Token).ConfigureAwait(false);

            var exception = (Exception)await channel.Serializer.Deserialize(channel.Reader, exceptionType, channel.Connection, cancel.Token).ConfigureAwait(false);

            throw exception;
        }
Ejemplo n.º 10
0
 public Task RemoteStart(IGenerateProxies proxyGenerator) => throw new NotSupportedException();
Ejemplo n.º 11
0
 public Task LocalStart(IGenerateProxies proxyGenerator, ConstructorInfo ctor, bool hostInstance, params object[] arguments) => throw new NotSupportedException();