protected override void Connect()
        {
            // Wait for the first write, there's a chicken-and-egg problem with the pipe handle
            // I can only dispose the local handle after the first pipe read, which blocks
            // But I can only catch the pipe disposal from cancellation after the handle has been disposed
            Buffer.FillFromStream(PipeStream, CancellationToken);

            // Dispose the client handle if we asked for one
            // If we don't do this we won't get notified when the stream closes, see https://stackoverflow.com/q/39682602/807064
            if (_clientHandle != null)
            {
                PipeStream.DisposeLocalCopyOfClientHandle();
                _clientHandle = null;
            }
        }
예제 #2
0
        //MAIN
        private NKRemotingProxy(string ns, string id, int nativeSeqMax, NKScriptMessage message, NKScriptContext context, CancellationToken cancelToken)
        {
            this.context        = context;
            this._localHandlers = null;
            this.ns             = ns;

            this.cancelToken = cancelToken;

            var exe  = System.Reflection.Assembly.GetEntryAssembly().Location;
            var path = System.IO.Path.GetDirectoryName(exe);
            ProcessStartInfo startInfo = Process.GetCurrentProcess().StartInfo;

            startInfo.FileName         = exe;
            startInfo.WorkingDirectory = path;
            startInfo.UseShellExecute  = false;

            var syncPipeOut   = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
            var syncPipeIn    = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
            var pipeOutHandle = syncPipeOut.GetClientHandleAsString();
            var pipeInHandle  = syncPipeIn.GetClientHandleAsString();

            this.syncPipeOut = syncPipeOut;
            this.syncPipeIn  = syncPipeIn;

            startInfo.Arguments = "NKR=" + buildInitMessage(pipeOutHandle, pipeInHandle);

            this.id = id;
            process = Process.Start(startInfo);
            NKEventEmitter.global.emit <string>("NKS.ProcessAdded", id, false);
            process.EnableRaisingEvents = true;
            process.Exited += Process_Exited;

            var pipeName  = Convert.ToBase64String(getUniqueKey());
            var asyncPipe = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous | PipeOptions.WriteThrough);

            this.asyncPipe = asyncPipe;
            NKScriptChannel.nativeFirstSequence -= 5;

            string nativeFirstSeq = NKScriptChannel.nativeFirstSequence.ToString();

            var handshake = new NKRemotingMessage();

            handshake.command = NKRemotingMessage.Command.NKRemotingHandshake;
            handshake.args    = new string[] { pipeName, ns, id, nativeSeqMax.ToString() };

            syncPipeOut.WriteByte(100);
            syncPipeOut.Flush();
            syncPipeOut.WaitForPipeDrain();
            syncPipeOut.DisposeLocalCopyOfClientHandle();
            syncPipeIn.DisposeLocalCopyOfClientHandle();

            writeObject(syncPipeOut, handshake);
            syncPipeOut.WaitForPipeDrain();

            var handshakeReply = readObject(syncPipeIn);

            if (handshakeReply == null || handshakeReply.command != NKRemotingMessage.Command.NKRemotingHandshake)
            {
                Environment.Exit(911);
            }

            asyncPipe.WaitForConnection();
            cancelToken.Register(requestClientTeardown);
            var nkready = readObject(asyncPipe);

            if (nkready == null || nkready.command != NKRemotingMessage.Command.NKRemotingReady)
            {
                Environment.Exit(910);
            }

            Task.Factory.StartNew((s) => _processServerMessages(asyncPipe), null, cancelToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
            NKEventEmitter.global.forward <NKEvent>(eventForwarderFromMain);
        }