public Echo(Options options) { log.Info("creating echo host"); log.DebugFormat("create interprocess input pipe (handle={0})", options.pipeIn); pipeIn = new AnonymousPipeClientStream(PipeDirection.In, options.pipeIn); pipeReader = new StreamReader(pipeIn); log.DebugFormat("create interprocess output pipe (handle={0})", options.pipeOut); pipeOut = new AnonymousPipeClientStream(PipeDirection.Out, options.pipeOut); pipeWriter = new StreamWriter(pipeOut); log.Debug("create native messaging port"); port = new Port(pipeIn, pipeOut); log.Debug("create stop event"); stop = new ManualResetEvent(false); log.Debug("synchronize processes"); string sync = pipeReader.ReadLine(); log.DebugFormat("sent {0}", sync); pipeWriter.WriteLine(sync); pipeWriter.Flush(); log.DebugFormat("received {0}", sync); pipeOut.WaitForPipeDrain(); log.Info("created echo host"); }
/// <summary> /// Überträgt ein Objekt in eine Kommunikationseinheit. /// </summary> /// <param name="pipe">Die Kommunikationseinheit.</param> /// <param name="serializer">Die Serialisierungsinstanz.</param> /// <param name="instance">Das betroffene Objekt.</param> internal static void SendToPipe( PipeStream pipe, XmlSerializer serializer, object instance ) { // Create helper using (var temp = new MemoryStream()) { // Create writer configuration var settings = new XmlWriterSettings { CheckCharacters = false }; // Create using (var writer = XmlWriter.Create( temp, settings )) serializer.Serialize( writer, instance ); // Read data and create buffer for length var len = new byte[sizeof( long )]; var data = temp.ToArray(); // Lock briefly var lenLock = GCHandle.Alloc( len, GCHandleType.Pinned ); try { // Fill Marshal.WriteInt64( lenLock.AddrOfPinnedObject(), data.LongLength ); } finally { // Release lenLock.Free(); } // Send all pipe.Write( len, 0, len.Length ); // Write in blocks for (int n = 0; n < data.Length; ) { // Block size int block = Math.Min( BlockSize, data.Length - n ); // Send chunck pipe.Write( data, n, block ); pipe.Flush(); // Advance n += block; } // Flush pipe.Flush(); pipe.WaitForPipeDrain(); } }
protected void HandlePipeConnection(PipeStream pipeStream, IDictionary<string, object> initialMessage) { // You think we'd scope these with using() right? They are IDisposable // after all... but nope, the implementation of these is such that // disposing of them also disposes the underlying stream. Leaving us // with a double (or triple if we close the pipeServer stream ourselves) // close. Yay. Instead we abandoned these to the GC knowing that they // are only wrappers anyway and have/use little/no resources of their own. BinaryReader reader = new BinaryReader(pipeStream, Encoding.Unicode); BinaryWriter writer = new BinaryWriter(pipeStream, Encoding.Unicode); try { // If we should announce with a specific message, do so if (initialMessage != null) { WriteMessage(writer, initialMessage); } // So long as our Func<> returns true, we keep going. When it returns false, // it is done and its time to closeup and look for another client. while (StreamAction(reader, writer)) { } } catch(Exception e) { LibraryLogging.Error("Error while using pipe connection: {0}", e); } try { pipeStream.Flush(); pipeStream.WaitForPipeDrain(); pipeStream.Close(); } catch(Exception e) { LibraryLogging.Error("Error while flushing/closing pipe connection: {0}", e); } }
//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); }