Compare commits

...
1 Commits
5 changed files with 141 additions and 36 deletions

No files matched your search

@@ -5,6 +5,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Fleck" Version="1.0.3" />
<PackageReference Include="MvvmLightLibs" Version="5.4.1" />
</ItemGroup>
@@ -1,11 +1,16 @@
using FluentTerminal.App.Services;
using Fleck;
using FluentTerminal.App.Services;
using FluentTerminal.Models;
using FluentTerminal.Models.Enums;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace FluentTerminal.App.ViewModels
@@ -30,6 +35,8 @@ namespace FluentTerminal.App.ViewModels
private readonly IApplicationView _applicationView;
private readonly IDispatcherTimer _resizeOverlayTimer;
private readonly IClipboardService _clipboardService;
private IWebSocketConnection _webSocket;
private NamedPipeClientStream _namedPipe;
public TerminalViewModel(int id, ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, string startupDirectory, ShellProfile shellProfile,
@@ -187,7 +194,37 @@ namespace FluentTerminal.App.ViewModels
DefaultTitle = response.ShellExecutableName;
Title = DefaultTitle;
await _terminalView.ConnectToSocket(response.WebSocketUrl).ConfigureAwait(true);
_namedPipe = new NamedPipeClientStream(".", response.PipeName, PipeDirection.InOut, PipeOptions.None);
if (!_namedPipe.IsConnected)
{
_namedPipe.Connect();
}
var webSocketUrl = "ws://127.0.0.1:" + response.Port;
var webSocketServer = new WebSocketServer(webSocketUrl);
webSocketServer.Start(socket =>
{
_webSocket = socket;
socket.OnOpen = () =>
{
Console.WriteLine("open");
//_connectedEvent.Set();
};
socket.OnClose = () =>
{
Console.WriteLine("closing");
_namedPipe.Close();
};
socket.OnMessage = message =>
{
var bytes = Encoding.UTF8.GetBytes(message);
_namedPipe.Write(bytes, 0, bytes.Length);
};
});
ListenToNamedPipe();
await _terminalView.ConnectToSocket(webSocketUrl).ConfigureAwait(true);
Initialized = true;
}
else
@@ -198,6 +235,26 @@ namespace FluentTerminal.App.ViewModels
await FocusTerminal().ConfigureAwait(true);
}
private void ListenToNamedPipe()
{
Task.Run(async () =>
{
var reader = new StreamReader(_namedPipe);
do
{
var offset = 0;
var buffer = new char[1024];
var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset);
if (readChars > 0)
{
await _webSocket.Send(new String(buffer));
}
}
while (!reader.EndOfStream);
_webSocket.Close();
});
}
private async Task InvokeCloseRequested()
{
if (_applicationSettings.ConfirmClosingTabs)
@@ -311,5 +368,34 @@ namespace FluentTerminal.App.ViewModels
ShowSearchPanel = false;
_terminalView.FocusTerminal();
}
private const int FirstDynamicPort = 49151;
public static int? GetAvailablePort()
{
var usedPorts = new List<int>();
var properties = IPGlobalProperties.GetIPGlobalProperties();
var connections = properties.GetActiveTcpConnections();
usedPorts.AddRange(connections.Where(c => c.LocalEndPoint.Port >= FirstDynamicPort).Select(c => c.LocalEndPoint.Port));
var endPoints = properties.GetActiveTcpListeners();
usedPorts.AddRange(endPoints.Where(e => e.Port >= FirstDynamicPort).Select(e => e.Port));
endPoints = properties.GetActiveUdpListeners();
usedPorts.AddRange(endPoints.Where(e => e.Port >= FirstDynamicPort).Select(e => e.Port));
usedPorts.Sort();
for (var i = FirstDynamicPort; i < UInt16.MaxValue; i++)
{
if (!usedPorts.Contains(i))
{
return i;
}
}
return null;
}
}
}
@@ -4,8 +4,9 @@
{
public int Id { get; set; }
public bool Success { get; set; }
public string WebSocketUrl { get; set; }
public int Port { get; set; }
public string Error { get; set; }
public string ShellExecutableName { get; set; }
public string PipeName { get; set; }
}
}
@@ -1,10 +1,8 @@
using Fleck;
using FluentTerminal.Models;
using FluentTerminal.Models;
using FluentTerminal.Models.Requests;
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static winpty.WinPty;
@@ -18,7 +16,7 @@ namespace FluentTerminal.SystemTray.Services
private IntPtr _handle;
private Stream _stdin;
private Stream _stdout;
private IWebSocketConnection _webSocket;
private NamedPipeServerStream _outServer;
public TerminalSession(CreateTerminalRequest request)
{
@@ -72,29 +70,17 @@ namespace FluentTerminal.SystemTray.Services
Id = port.Value;
_connectedEvent = new ManualResetEventSlim(false);
WebSocketUrl = "ws://127.0.0.1:" + port;
var webSocketServer = new WebSocketServer(WebSocketUrl);
webSocketServer.Start(socket =>
{
_webSocket = socket;
socket.OnOpen = () =>
{
Console.WriteLine("open");
_connectedEvent.Set();
};
socket.OnClose = () =>
{
Console.WriteLine("closing");
ConnectionClosed?.Invoke(this, EventArgs.Empty);
};
socket.OnMessage = message =>
{
var bytes = Encoding.UTF8.GetBytes(message);
_stdin.Write(bytes, 0, bytes.Length);
};
});
PipeName = @"LOCAL\" + Guid.NewGuid().ToString();
_outServer = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None);
StreamReader reader = new StreamReader(_outServer);
ListenToStdOut();
ListenToNamedPipe();
}
~TerminalSession()
@@ -114,7 +100,9 @@ namespace FluentTerminal.SystemTray.Services
public event EventHandler ConnectionClosed;
public int Id { get; }
public string WebSocketUrl { get; }
public string PipeName { get; }
public string ShellExecutableName { get; }
public void Dispose()
@@ -178,12 +166,18 @@ namespace FluentTerminal.SystemTray.Services
return pipe;
}
private void ListenToStdOut()
private void ListenToNamedPipe()
{
new NotificationService().ShowNotification("DEBUG", "wating now");
_outServer.WaitForConnection();
new NotificationService().ShowNotification("DEBUG", "connected");
Task.Run(async () =>
{
_connectedEvent.Wait();
var reader = new StreamReader(_stdout);
//_connectedEvent.Wait();
var reader = new StreamReader(_outServer);
var writer = new StreamWriter(_stdin);
do
{
var offset = 0;
@@ -191,12 +185,34 @@ namespace FluentTerminal.SystemTray.Services
var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset);
if (readChars > 0)
{
await _webSocket.Send(new String(buffer));
writer.Write(buffer, 0, readChars);
}
}
while (!reader.EndOfStream);
_webSocket.Close();
_stdin.Close();
});
}
private void ListenToStdOut()
{
Task.Run(async () =>
{
var reader = new StreamReader(_stdout);
var writer = new StreamWriter(_outServer);
do
{
var offset = 0;
var buffer = new char[1024];
var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset);
if (readChars > 0)
{
writer.Write(buffer, 0, readChars);
}
}
while (!reader.EndOfStream);
_outServer.Close();
});
}
}
}
}
@@ -35,7 +35,8 @@ namespace FluentTerminal.SystemTray.Services
{
Success = true,
Id = terminal.Id,
WebSocketUrl = terminal.WebSocketUrl,
Port = Utilities.GetAvailablePort().Value,
PipeName = terminal.PipeName,
ShellExecutableName = terminal.ShellExecutableName
};
}