public override async Task <Router> CreateRouterAsync(CancellationToken token) { Stream tcpServerStream = null; Stream ipcServerStream = null; _logger?.LogDebug($"Trying to create new router instance."); try { using CancellationTokenSource cancelRouter = CancellationTokenSource.CreateLinkedTokenSource(token); // Get new tcp server endpoint. using var tcpServerStreamTask = _tcpServerRouterFactory.AcceptTcpStreamAsync(cancelRouter.Token); // Get new ipc server endpoint. using var ipcServerStreamTask = _ipcServerRouterFactory.AcceptIpcStreamAsync(cancelRouter.Token); await Task.WhenAny(ipcServerStreamTask, tcpServerStreamTask).ConfigureAwait(false); if (IsCompletedSuccessfully(ipcServerStreamTask) && IsCompletedSuccessfully(tcpServerStreamTask)) { ipcServerStream = ipcServerStreamTask.Result; tcpServerStream = tcpServerStreamTask.Result; } else if (IsCompletedSuccessfully(ipcServerStreamTask)) { ipcServerStream = ipcServerStreamTask.Result; // We have a valid ipc stream and a pending tcp accept. Wait for completion // or disconnect of ipc stream. using var checkIpcStreamTask = IsStreamConnectedAsync(ipcServerStream, cancelRouter.Token); // Wait for at least completion of one task. await Task.WhenAny(tcpServerStreamTask, checkIpcStreamTask).ConfigureAwait(false); // Cancel out any pending tasks not yet completed. cancelRouter.Cancel(); try { await Task.WhenAll(tcpServerStreamTask, checkIpcStreamTask).ConfigureAwait(false); } catch (Exception) { // Check if we have an accepted tcp stream. if (IsCompletedSuccessfully(tcpServerStreamTask)) { tcpServerStreamTask.Result?.Dispose(); } if (checkIpcStreamTask.IsFaulted) { _logger?.LogInformation("Broken ipc connection detected, aborting tcp connection."); checkIpcStreamTask.GetAwaiter().GetResult(); } throw; } tcpServerStream = tcpServerStreamTask.Result; } else if (IsCompletedSuccessfully(tcpServerStreamTask)) { tcpServerStream = tcpServerStreamTask.Result; // We have a valid tcp stream and a pending ipc accept. Wait for completion // or disconnect of tcp stream. using var checkTcpStreamTask = IsStreamConnectedAsync(tcpServerStream, cancelRouter.Token); // Wait for at least completion of one task. await Task.WhenAny(ipcServerStreamTask, checkTcpStreamTask).ConfigureAwait(false); // Cancel out any pending tasks not yet completed. cancelRouter.Cancel(); try { await Task.WhenAll(ipcServerStreamTask, checkTcpStreamTask).ConfigureAwait(false); } catch (Exception) { // Check if we have an accepted ipc stream. if (IsCompletedSuccessfully(ipcServerStreamTask)) { ipcServerStreamTask.Result?.Dispose(); } if (checkTcpStreamTask.IsFaulted) { _logger?.LogInformation("Broken tcp connection detected, aborting ipc connection."); checkTcpStreamTask.GetAwaiter().GetResult(); } throw; } ipcServerStream = ipcServerStreamTask.Result; } else { // Error case, cancel out. wait and throw exception. cancelRouter.Cancel(); try { await Task.WhenAll(ipcServerStreamTask, tcpServerStreamTask).ConfigureAwait(false); } catch (Exception) { // Check if we have an ipc stream. if (IsCompletedSuccessfully(ipcServerStreamTask)) { ipcServerStreamTask.Result?.Dispose(); } throw; } } } catch (Exception) { _logger?.LogDebug("Failed creating new router instance."); // Cleanup and rethrow. ipcServerStream?.Dispose(); tcpServerStream?.Dispose(); throw; } // Create new router. _logger?.LogDebug("New router instance successfully created."); return(new Router(ipcServerStream, tcpServerStream, _logger)); }
public override async Task <Router> CreateRouterAsync(CancellationToken token) { Stream tcpServerStream = null; Stream ipcClientStream = null; _logger?.LogDebug("Trying to create a new router instance."); try { using CancellationTokenSource cancelRouter = CancellationTokenSource.CreateLinkedTokenSource(token); // Get new server endpoint. tcpServerStream = await _tcpServerRouterFactory.AcceptTcpStreamAsync(cancelRouter.Token).ConfigureAwait(false); // Get new client endpoint. using var ipcClientStreamTask = _ipcClientRouterFactory.ConnectIpcStreamAsync(cancelRouter.Token); // We have a valid tcp stream and a pending ipc stream. Wait for completion // or disconnect of tcp stream. using var checkTcpStreamTask = IsStreamConnectedAsync(tcpServerStream, cancelRouter.Token); // Wait for at least completion of one task. await Task.WhenAny(ipcClientStreamTask, checkTcpStreamTask).ConfigureAwait(false); // Cancel out any pending tasks not yet completed. cancelRouter.Cancel(); try { await Task.WhenAll(ipcClientStreamTask, checkTcpStreamTask).ConfigureAwait(false); } catch (Exception) { // Check if we have an accepted ipc stream. if (IsCompletedSuccessfully(ipcClientStreamTask)) { ipcClientStreamTask.Result?.Dispose(); } if (checkTcpStreamTask.IsFaulted) { _logger?.LogInformation("Broken tcp connection detected, aborting ipc connection."); checkTcpStreamTask.GetAwaiter().GetResult(); } throw; } ipcClientStream = ipcClientStreamTask.Result; try { // TcpServer consumes advertise message, needs to be replayed back to ipc client stream. Use router process ID as representation. await IpcAdvertise.SerializeAsync(ipcClientStream, _tcpServerRouterFactory.RuntimeInstanceId, (ulong)Process.GetCurrentProcess().Id, token).ConfigureAwait(false); } catch (Exception) { _logger?.LogDebug("Failed sending advertise message."); throw; } } catch (Exception) { _logger?.LogDebug("Failed creating new router instance."); // Cleanup and rethrow. tcpServerStream?.Dispose(); ipcClientStream?.Dispose(); throw; } // Create new router. _logger?.LogDebug("New router instance successfully created."); return(new Router(ipcClientStream, tcpServerStream, _logger, (ulong)IpcAdvertise.V1SizeInBytes)); }