Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76cb528eb4 |
No files matched your search
@@ -5,6 +5,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Fleck" Version="1.0.3" />
|
||||||
<PackageReference Include="MvvmLightLibs" Version="5.4.1" />
|
<PackageReference Include="MvvmLightLibs" Version="5.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
using FluentTerminal.App.Services;
|
using Fleck;
|
||||||
|
using FluentTerminal.App.Services;
|
||||||
using FluentTerminal.Models;
|
using FluentTerminal.Models;
|
||||||
using FluentTerminal.Models.Enums;
|
using FluentTerminal.Models.Enums;
|
||||||
using GalaSoft.MvvmLight;
|
using GalaSoft.MvvmLight;
|
||||||
using GalaSoft.MvvmLight.Command;
|
using GalaSoft.MvvmLight.Command;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Pipes;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FluentTerminal.App.ViewModels
|
namespace FluentTerminal.App.ViewModels
|
||||||
@@ -30,6 +35,8 @@ namespace FluentTerminal.App.ViewModels
|
|||||||
private readonly IApplicationView _applicationView;
|
private readonly IApplicationView _applicationView;
|
||||||
private readonly IDispatcherTimer _resizeOverlayTimer;
|
private readonly IDispatcherTimer _resizeOverlayTimer;
|
||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
|
private IWebSocketConnection _webSocket;
|
||||||
|
private NamedPipeClientStream _namedPipe;
|
||||||
|
|
||||||
public TerminalViewModel(int id, ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
|
public TerminalViewModel(int id, ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService,
|
||||||
IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, string startupDirectory, ShellProfile shellProfile,
|
IKeyboardCommandService keyboardCommandService, ApplicationSettings applicationSettings, string startupDirectory, ShellProfile shellProfile,
|
||||||
@@ -187,7 +194,37 @@ namespace FluentTerminal.App.ViewModels
|
|||||||
DefaultTitle = response.ShellExecutableName;
|
DefaultTitle = response.ShellExecutableName;
|
||||||
Title = DefaultTitle;
|
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;
|
Initialized = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -198,6 +235,26 @@ namespace FluentTerminal.App.ViewModels
|
|||||||
await FocusTerminal().ConfigureAwait(true);
|
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()
|
private async Task InvokeCloseRequested()
|
||||||
{
|
{
|
||||||
if (_applicationSettings.ConfirmClosingTabs)
|
if (_applicationSettings.ConfirmClosingTabs)
|
||||||
@@ -311,5 +368,34 @@ namespace FluentTerminal.App.ViewModels
|
|||||||
ShowSearchPanel = false;
|
ShowSearchPanel = false;
|
||||||
_terminalView.FocusTerminal();
|
_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 int Id { get; set; }
|
||||||
public bool Success { get; set; }
|
public bool Success { get; set; }
|
||||||
public string WebSocketUrl { get; set; }
|
public int Port { get; set; }
|
||||||
public string Error { get; set; }
|
public string Error { get; set; }
|
||||||
public string ShellExecutableName { 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 FluentTerminal.Models.Requests;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Pipes;
|
using System.IO.Pipes;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static winpty.WinPty;
|
using static winpty.WinPty;
|
||||||
@@ -18,7 +16,7 @@ namespace FluentTerminal.SystemTray.Services
|
|||||||
private IntPtr _handle;
|
private IntPtr _handle;
|
||||||
private Stream _stdin;
|
private Stream _stdin;
|
||||||
private Stream _stdout;
|
private Stream _stdout;
|
||||||
private IWebSocketConnection _webSocket;
|
private NamedPipeServerStream _outServer;
|
||||||
|
|
||||||
public TerminalSession(CreateTerminalRequest request)
|
public TerminalSession(CreateTerminalRequest request)
|
||||||
{
|
{
|
||||||
@@ -72,29 +70,17 @@ namespace FluentTerminal.SystemTray.Services
|
|||||||
|
|
||||||
Id = port.Value;
|
Id = port.Value;
|
||||||
_connectedEvent = new ManualResetEventSlim(false);
|
_connectedEvent = new ManualResetEventSlim(false);
|
||||||
WebSocketUrl = "ws://127.0.0.1:" + port;
|
|
||||||
var webSocketServer = new WebSocketServer(WebSocketUrl);
|
PipeName = @"LOCAL\" + Guid.NewGuid().ToString();
|
||||||
webSocketServer.Start(socket =>
|
|
||||||
{
|
_outServer = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None);
|
||||||
_webSocket = socket;
|
|
||||||
socket.OnOpen = () =>
|
StreamReader reader = new StreamReader(_outServer);
|
||||||
{
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
ListenToStdOut();
|
ListenToStdOut();
|
||||||
|
ListenToNamedPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
~TerminalSession()
|
~TerminalSession()
|
||||||
@@ -114,7 +100,9 @@ namespace FluentTerminal.SystemTray.Services
|
|||||||
public event EventHandler ConnectionClosed;
|
public event EventHandler ConnectionClosed;
|
||||||
|
|
||||||
public int Id { get; }
|
public int Id { get; }
|
||||||
public string WebSocketUrl { get; }
|
|
||||||
|
public string PipeName { get; }
|
||||||
|
|
||||||
public string ShellExecutableName { get; }
|
public string ShellExecutableName { get; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -178,12 +166,18 @@ namespace FluentTerminal.SystemTray.Services
|
|||||||
return pipe;
|
return pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListenToStdOut()
|
private void ListenToNamedPipe()
|
||||||
{
|
{
|
||||||
|
new NotificationService().ShowNotification("DEBUG", "wating now");
|
||||||
|
_outServer.WaitForConnection();
|
||||||
|
new NotificationService().ShowNotification("DEBUG", "connected");
|
||||||
|
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
_connectedEvent.Wait();
|
//_connectedEvent.Wait();
|
||||||
var reader = new StreamReader(_stdout);
|
var reader = new StreamReader(_outServer);
|
||||||
|
var writer = new StreamWriter(_stdin);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
@@ -191,11 +185,33 @@ namespace FluentTerminal.SystemTray.Services
|
|||||||
var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset);
|
var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset);
|
||||||
if (readChars > 0)
|
if (readChars > 0)
|
||||||
{
|
{
|
||||||
await _webSocket.Send(new String(buffer));
|
writer.Write(buffer, 0, readChars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!reader.EndOfStream);
|
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,
|
Success = true,
|
||||||
Id = terminal.Id,
|
Id = terminal.Id,
|
||||||
WebSocketUrl = terminal.WebSocketUrl,
|
Port = Utilities.GetAvailablePort().Value,
|
||||||
|
PipeName = terminal.PipeName,
|
||||||
ShellExecutableName = terminal.ShellExecutableName
|
ShellExecutableName = terminal.ShellExecutableName
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user