private static async Task WebSocketToPipeWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) { const int blockSize = 0x10000; var buffer = new MemoryStream(blockSize); while (true) { cancellationToken.ThrowIfCancellationRequested(); int index = (int)buffer.Length; buffer.SetLength(index + blockSize); buffer.TryGetBuffer(out ArraySegment <byte> bufferSegment); var wsrr = await socket.ReceiveAsync(new ArraySegment <byte>(bufferSegment.Array, index, blockSize), cancellationToken); buffer.SetLength(index + wsrr.Count); if (wsrr.CloseStatus != null) { break; } if (wsrr.EndOfMessage) { pipe.Write(buffer.ToArray()); buffer.SetLength(0); } } }
private async Task ClientToHostWorker(Stream stream, IMessagePipeEnd pipe) { using (stream) { while (true) { byte[] message; try { message = await pipe.ReadAsync(CommonStartup.CancellationToken); } catch (PipeDisconnectedException) { break; } var sizeBuf = BitConverter.GetBytes(message.Length); try { await stream.WriteAsync(sizeBuf, 0, sizeBuf.Length); await stream.WriteAsync(message, 0, message.Length); await stream.FlushAsync(); } catch (IOException) { break; } } } }
private static async Task PipeToWebSocketWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); var message = await pipe.ReadAsync(cancellationToken); await socket.SendAsync(new ArraySegment <byte>(message, 0, message.Length), WebSocketMessageType.Binary, true, cancellationToken); } }
private static async Task PipeToWebSocketWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); byte[] message; try { message = await pipe.ReadAsync(cancellationToken); } catch (PipeDisconnectedException) { break; } await socket.SendAsync(new ArraySegment<byte>(message, 0, message.Length), WebSocketMessageType.Binary, true, cancellationToken); } }
private static async Task PipeToWebSocketWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); byte[] message; try { message = await pipe.ReadAsync(cancellationToken); } catch (PipeDisconnectedException) { break; } await socket.SendAsync(new ArraySegment <byte>(message, 0, message.Length), WebSocketMessageType.Binary, true, cancellationToken); } }
private async Task ClientToHostWorker(Stream stream, IMessagePipeEnd pipe) { while (true) { var message = await pipe.ReadAsync(Program.CancellationToken); var sizeBuf = BitConverter.GetBytes(message.Length); try { await stream.WriteAsync(sizeBuf, 0, sizeBuf.Length); await stream.WriteAsync(message, 0, message.Length); await stream.FlushAsync(); } catch (IOException) { break; } } }
private async Task HostToClientWorker(Stream stream, IMessagePipeEnd pipe) { var sizeBuf = new byte[sizeof(int)]; while (true) { if (!await FillFromStreamAsync(stream, sizeBuf)) { break; } int size = BitConverter.ToInt32(sizeBuf, 0); var message = new byte[size]; if (!await FillFromStreamAsync(stream, message)) { break; } pipe.Write(message); } }
private static async Task WebSocketToPipeWorker(WebSocket socket, IMessagePipeEnd pipe, CancellationToken cancellationToken) { const int blockSize = 0x10000; var buffer = new MemoryStream(blockSize); while (true) { cancellationToken.ThrowIfCancellationRequested(); int index = (int)buffer.Length; buffer.SetLength(index + blockSize); var wsrr = await socket.ReceiveAsync(new ArraySegment<byte>(buffer.GetBuffer(), index, blockSize), cancellationToken); buffer.SetLength(index + wsrr.Count); if (wsrr.CloseStatus != null) { break; } else if (wsrr.EndOfMessage) { pipe.Write(buffer.ToArray()); buffer.SetLength(0); } } }
public WebSocketPipeAction(string id, IMessagePipeEnd pipe, ILogger logger) { _id = id; _pipe = pipe; _logger = logger; }
public void StartHost(string profilePath, string logFolder, ILogger outputLogger, LogVerbosity verbosity) { if (_hostEnd != null) { throw new InvalidOperationException("Host process is already running"); } var useridentity = User as WindowsIdentity; // In remote broker User Identity type is always WindowsIdentity string suppressUI = (useridentity == null) ? string.Empty : "--rhost-suppress-ui "; string isRepl = _isInteractive ? "--rhost-interactive " : string.Empty; string brokerPath = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath()); string rhostExePath = Path.Combine(brokerPath, RHostExe); string logFolderParam = string.IsNullOrEmpty(logFolder) ? string.Empty : Invariant($"--rhost-log-dir \"{logFolder}\""); string commandLine = Invariant($"\"{rhostExePath}\" {suppressUI}{isRepl}--rhost-name \"{Id}\" {logFolderParam} --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}"); var usernameBldr = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domainBldr = new StringBuilder(NativeMethods.CREDUI_MAX_DOMAIN_LENGTH + 1); // Get R_HOME value var shortHome = new StringBuilder(NativeMethods.MAX_PATH); NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity); Stream stdout, stdin, stderror; bool loggedOnUser = useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User; // build user environment block Win32EnvironmentBlock eb; if (loggedOnUser) { uint error = NativeMethods.CredUIParseUserName(User.Name, usernameBldr, usernameBldr.Capacity, domainBldr, domainBldr.Capacity); if (error != 0) { _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error); throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error)); } string username = usernameBldr.ToString(); string domain = domainBldr.ToString(); eb = CreateEnvironmentBlockForUser(useridentity, username, profilePath); } else { eb = Win32EnvironmentBlock.Create((useridentity ?? WindowsIdentity.GetCurrent()).Token); } // add additional variables to the environment block eb["R_HOME"] = shortHome.ToString(); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "R_HOME", eb["R_HOME"]); eb["PATH"] = Invariant($"{Interpreter.Info.BinPath};{Environment.GetEnvironmentVariable("PATH")}"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "PATH", eb["PATH"]); _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, commandLine); using (Win32NativeEnvironmentBlock nativeEnv = eb.GetNativeEnvironmentBlock()) { if (loggedOnUser) { _process = Win32Process.StartProcessAsUser(useridentity, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv, out stdin, out stdout, out stderror); } else { _process = Win32Process.StartProcessAsUser(null, rhostExePath, commandLine, Path.GetDirectoryName(rhostExePath), nativeEnv, out stdin, out stdout, out stderror); } } _process.Exited += delegate(object o, Win32ProcessExitEventArgs exitState){ _hostEnd?.Dispose(); _hostEnd = null; State = SessionState.Terminated; if (exitState.HasError()) { _sessionLogger.LogInformation(Resources.Error_ExitRHost, exitState.ExitCode); } }; _process.WaitForExit(250); if (_process.HasExited && _process.ExitCode < 0) { var message = ErrorCodeConverter.MessageFromErrorCode(_process.ExitCode); if (!string.IsNullOrEmpty(message)) { throw new Win32Exception(message); } throw new Win32Exception(_process.ExitCode); } _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name); var hostEnd = _pipe.ConnectHost(_process.ProcessId); _hostEnd = hostEnd; ClientToHostWorker(stdin, hostEnd).DoNotWait(); HostToClientWorker(stdout, hostEnd).DoNotWait(); HostToClientErrorWorker(stderror, _process.ProcessId, (int processid, string errdata) => { outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, processid, errdata); }).DoNotWait(); }
public WebSocketPipeAction(IMessagePipeEnd pipe, ILogger logger) { _pipe = pipe; _logger = logger; }
public WebSocketPipeAction(string id, IMessagePipeEnd pipe) { _id = id; _pipe = pipe; }
public void StartHost(SecureString password, string profilePath, ILogger outputLogger, LogVerbosity verbosity) { if (_hostEnd != null) { throw new InvalidOperationException("Host process is already running"); } var useridentity = User as WindowsIdentity; // In remote broker User Identity type is always WindowsIdentity string suppressUI = (useridentity == null) ? string.Empty : " --suppress-ui "; string brokerPath = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath()); string rhostExePath = Path.Combine(brokerPath, RHostExe); string arguments = Invariant($"{suppressUI}--rhost-name \"{Id}\" --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}"); var username = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domain = new StringBuilder(NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1); ProcessStartInfo psi = new ProcessStartInfo(rhostExePath) { UseShellExecute = false, CreateNoWindow = false, Arguments = arguments, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, LoadUserProfile = true }; if (useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User && password != null) { uint error = NativeMethods.CredUIParseUserName(User.Name, username, username.Capacity, domain, domain.Capacity); if (error != 0) { _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error); throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error)); } psi.Domain = domain.ToString(); psi.UserName = username.ToString(); psi.Password = password; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariableCreationBegin, User.Name, profilePath); // if broker and rhost are run as different users recreate user environment variables. psi.EnvironmentVariables["USERNAME"] = username.ToString(); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERNAME", psi.EnvironmentVariables["USERNAME"]); psi.EnvironmentVariables["HOMEDRIVE"] = profilePath.Substring(0, 2); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEDRIVE", psi.EnvironmentVariables["HOMEDRIVE"]); psi.EnvironmentVariables["HOMEPATH"] = profilePath.Substring(2); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEPATH", psi.EnvironmentVariables["HOMEPATH"]); psi.EnvironmentVariables["USERPROFILE"] = Invariant($"{psi.EnvironmentVariables["HOMEDRIVE"]}{psi.EnvironmentVariables["HOMEPATH"]}"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERPROFILE", psi.EnvironmentVariables["USERPROFILE"]); psi.EnvironmentVariables["APPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Roaming"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "APPDATA", psi.EnvironmentVariables["APPDATA"]); psi.EnvironmentVariables["LOCALAPPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Local"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "LOCALAPPDATA", psi.EnvironmentVariables["LOCALAPPDATA"]); psi.EnvironmentVariables["TEMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TEMP", psi.EnvironmentVariables["TEMP"]); psi.EnvironmentVariables["TMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TMP", psi.EnvironmentVariables["TMP"]); } var shortHome = new StringBuilder(NativeMethods.MAX_PATH); NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity); psi.EnvironmentVariables["R_HOME"] = shortHome.ToString(); psi.EnvironmentVariables["PATH"] = Interpreter.Info.BinPath + ";" + Environment.GetEnvironmentVariable("PATH"); psi.WorkingDirectory = Path.GetDirectoryName(rhostExePath); _process = new Process { StartInfo = psi, EnableRaisingEvents = true, }; _process.ErrorDataReceived += (sender, e) => { var process = (Process)sender; outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, process.Id, e.Data); }; _process.Exited += delegate { _hostEnd?.Dispose(); _hostEnd = null; State = SessionState.Terminated; }; _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, rhostExePath, arguments); try { StartSession(); } catch(Exception ex) { _sessionLogger.LogError(Resources.Error_RHostFailedToStart, ex.Message); throw; } _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name); _process.BeginErrorReadLine(); var hostEnd = _pipe.ConnectHost(_process.Id); _hostEnd = hostEnd; ClientToHostWorker(_process.StandardInput.BaseStream, hostEnd).DoNotWait(); HostToClientWorker(_process.StandardOutput.BaseStream, hostEnd).DoNotWait(); }
public void StartHost(SecureString password, string profilePath, ILogger outputLogger, LogVerbosity verbosity) { if (_hostEnd != null) { throw new InvalidOperationException("Host process is already running"); } string brokerPath = Path.GetDirectoryName(typeof(Program).Assembly.GetAssemblyPath()); string rhostExePath = Path.Combine(brokerPath, RHostExe); string arguments = Invariant($"--rhost-name \"{Id}\" --rhost-log-verbosity {(int)verbosity} {CommandLineArguments}"); var username = new StringBuilder(NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1); var domain = new StringBuilder(NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1); ProcessStartInfo psi = new ProcessStartInfo(rhostExePath) { UseShellExecute = false, CreateNoWindow = false, Arguments = arguments, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, LoadUserProfile = true }; var useridentity = User as WindowsIdentity; if (useridentity != null && WindowsIdentity.GetCurrent().User != useridentity.User && password != null) { uint error = NativeMethods.CredUIParseUserName(User.Name, username, username.Capacity, domain, domain.Capacity); if (error != 0) { _sessionLogger.LogError(Resources.Error_UserNameParse, User.Name, error); throw new ArgumentException(Resources.Error_UserNameParse.FormatInvariant(User.Name, error)); } psi.Domain = domain.ToString(); psi.UserName = username.ToString(); psi.Password = password; _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariableCreationBegin, User.Name, profilePath); // if broker and rhost are run as different users recreate user environment variables. psi.EnvironmentVariables["USERNAME"] = username.ToString(); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERNAME", psi.EnvironmentVariables["USERNAME"]); psi.EnvironmentVariables["HOMEDRIVE"] = profilePath.Substring(0, 2); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEDRIVE", psi.EnvironmentVariables["HOMEDRIVE"]); psi.EnvironmentVariables["HOMEPATH"] = profilePath.Substring(2); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "HOMEPATH", psi.EnvironmentVariables["HOMEPATH"]); psi.EnvironmentVariables["USERPROFILE"] = Invariant($"{psi.EnvironmentVariables["HOMEDRIVE"]}{psi.EnvironmentVariables["HOMEPATH"]}"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "USERPROFILE", psi.EnvironmentVariables["USERPROFILE"]); psi.EnvironmentVariables["APPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Roaming"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "APPDATA", psi.EnvironmentVariables["APPDATA"]); psi.EnvironmentVariables["LOCALAPPDATA"] = Invariant($"{psi.EnvironmentVariables["USERPROFILE"]}\\AppData\\Local"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "LOCALAPPDATA", psi.EnvironmentVariables["LOCALAPPDATA"]); psi.EnvironmentVariables["TEMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TEMP", psi.EnvironmentVariables["TEMP"]); psi.EnvironmentVariables["TMP"] = Invariant($"{psi.EnvironmentVariables["LOCALAPPDATA"]}\\Temp"); _sessionLogger.LogTrace(Resources.Trace_EnvironmentVariable, "TMP", psi.EnvironmentVariables["TMP"]); } var shortHome = new StringBuilder(NativeMethods.MAX_PATH); NativeMethods.GetShortPathName(Interpreter.Info.Path, shortHome, shortHome.Capacity); psi.EnvironmentVariables["R_HOME"] = shortHome.ToString(); psi.EnvironmentVariables["PATH"] = Interpreter.Info.BinPath + ";" + Environment.GetEnvironmentVariable("PATH"); psi.WorkingDirectory = Path.GetDirectoryName(rhostExePath); _process = new Process { StartInfo = psi, EnableRaisingEvents = true, }; _process.ErrorDataReceived += (sender, e) => { var process = (Process)sender; outputLogger?.LogTrace(Resources.Trace_ErrorDataReceived, process.Id, e.Data); }; _process.Exited += delegate { _hostEnd?.Dispose(); _hostEnd = null; State = SessionState.Terminated; }; _sessionLogger.LogInformation(Resources.Info_StartingRHost, Id, User.Name, rhostExePath, arguments); try { StartSession(); } catch (Exception ex) { _sessionLogger.LogError(Resources.Error_RHostFailedToStart, ex.Message); throw; } _sessionLogger.LogInformation(Resources.Info_StartedRHost, Id, User.Name); _process.BeginErrorReadLine(); var hostEnd = _pipe.ConnectHost(_process.Id); _hostEnd = hostEnd; ClientToHostWorker(_process.StandardInput.BaseStream, hostEnd).DoNotWait(); HostToClientWorker(_process.StandardOutput.BaseStream, hostEnd).DoNotWait(); }
private async Task ClientToHostWorker(Stream stream, IMessagePipeEnd pipe) { using (stream) { while (true) { byte[] message; try { message = await pipe.ReadAsync(Program.CancellationToken); } catch (PipeDisconnectedException) { break; } var sizeBuf = BitConverter.GetBytes(message.Length); try { await stream.WriteAsync(sizeBuf, 0, sizeBuf.Length); await stream.WriteAsync(message, 0, message.Length); await stream.FlushAsync(); } catch (IOException) { break; } } } }