Create Telnet connection type and default loopback profile for… (#3858)
For our Universal terminal for development purposes, we will use telnet to escape the universal application container and empower developers to debug/diagnose issues with their own machine on loopback to the already-elevated telnet context.
This commit is contained in:
parent
dd1c7b3e52
commit
402b7ff0e0
30
NOTICE.md
30
NOTICE.md
|
@ -47,3 +47,33 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## telnetpp
|
||||
|
||||
**Source**: https://github.com/KazDragon/telnetpp
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2017 Matthew Chaplain a.k.a KazDragon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 647 B |
Binary file not shown.
After Width: | Height: | Size: 787 B |
|
@ -49,8 +49,8 @@ namespace winrt::TerminalApp::implementation
|
|||
if (content == nullptr)
|
||||
{
|
||||
auto logic = Logic();
|
||||
logic.RunAsUwp(); // Must set UWP status first, settings might change based on it.
|
||||
logic.LoadSettings();
|
||||
logic.RunAsUwp();
|
||||
logic.Create();
|
||||
|
||||
auto page = logic.GetRoot().as<TerminalPage>();
|
||||
|
|
|
@ -129,9 +129,24 @@ namespace winrt::TerminalApp::implementation
|
|||
_root = winrt::make_self<TerminalPage>();
|
||||
}
|
||||
|
||||
// Method Decscription:
|
||||
// - Called around the codebase to discover if this is a UWP where we need to turn off specific settings.
|
||||
// Arguments:
|
||||
// - <none> - reports internal state
|
||||
// Return Value:
|
||||
// - True if UWP, false otherwise.
|
||||
bool AppLogic::IsUwp() const noexcept
|
||||
{
|
||||
return _isUwp;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called by UWP context invoker to let us know that we may have to change some of our behaviors
|
||||
// for being a UWP
|
||||
// Arguments:
|
||||
// - <none> (sets to UWP = true, one way change)
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppLogic::RunAsUwp()
|
||||
{
|
||||
_isUwp = true;
|
||||
|
@ -438,7 +453,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
try
|
||||
{
|
||||
auto newSettings = CascadiaSettings::LoadAll();
|
||||
auto newSettings = _isUwp ? CascadiaSettings::LoadUniversal() : CascadiaSettings::LoadAll();
|
||||
_settings = std::move(newSettings);
|
||||
const auto& warnings = _settings->GetWarnings();
|
||||
hr = warnings.size() == 0 ? S_OK : S_FALSE;
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace winrt::TerminalApp::implementation
|
|||
~AppLogic() = default;
|
||||
|
||||
void Create();
|
||||
bool IsUwp() const noexcept;
|
||||
void RunAsUwp();
|
||||
void LoadSettings();
|
||||
[[nodiscard]] std::shared_ptr<::TerminalApp::CascadiaSettings> GetSettings() const noexcept;
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace TerminalApp
|
|||
// registered?" when it definitely is.
|
||||
void Create();
|
||||
|
||||
Boolean IsUwp();
|
||||
void RunAsUwp();
|
||||
|
||||
void LoadSettings();
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
|
||||
static std::unique_ptr<CascadiaSettings> LoadDefaults();
|
||||
static std::unique_ptr<CascadiaSettings> LoadAll();
|
||||
static std::unique_ptr<CascadiaSettings> LoadUniversal();
|
||||
|
||||
static const CascadiaSettings& GetCurrentAppSettings();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
// defaults.h is a file containing the default json settings in a std::string_view
|
||||
#include "defaults.h"
|
||||
#include "defaults-universal.h"
|
||||
// userDefault.h is like the above, but with a default template for the user's profiles.json.
|
||||
#include "userDefaults.h"
|
||||
// Both defaults.h and userDefaults.h are generated at build time into the
|
||||
|
@ -121,6 +122,29 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadAll()
|
|||
return resultPtr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Loads a batch of settings curated for the Universal variant of the terminal app
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a unique_ptr to a CascadiaSettings with the connection types and settings for Universal terminal
|
||||
std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadUniversal()
|
||||
{
|
||||
// We're going to do this ourselves because we want to exclude almost everything
|
||||
// from the special Universal-for-developers configuration
|
||||
|
||||
// Create settings and get the universal defaults loaded up.
|
||||
auto resultPtr = std::make_unique<CascadiaSettings>();
|
||||
resultPtr->_ParseJsonString(DefaultUniversalJson, true);
|
||||
resultPtr->LayerJson(resultPtr->_defaultSettings);
|
||||
|
||||
// Now validate.
|
||||
// If this throws, the app will catch it and use the default settings
|
||||
resultPtr->_ValidateSettings();
|
||||
|
||||
return resultPtr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a new CascadiaSettings object initialized with settings from the
|
||||
// hardcoded defaults.json.
|
||||
|
|
|
@ -18,4 +18,5 @@ Author(s):
|
|||
|
||||
static constexpr std::wstring_view WslGeneratorNamespace{ L"Windows.Terminal.Wsl" };
|
||||
static constexpr std::wstring_view AzureGeneratorNamespace{ L"Windows.Terminal.Azure" };
|
||||
static constexpr std::wstring_view TelnetGeneratorNamespace{ L"Windows.Terminal.Telnet" };
|
||||
static constexpr std::wstring_view PowershellCoreGeneratorNamespace{ L"Windows.Terminal.PowershellCore" };
|
||||
|
|
19
src/cascadia/TerminalApp/TelnetGenerator.h
Normal file
19
src/cascadia/TerminalApp/TelnetGenerator.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- TelnetGenerator
|
||||
|
||||
Abstract:
|
||||
- Information needed to detect a Telnet connection type.
|
||||
|
||||
Author(s):
|
||||
- Michael Niksa - 2019-12-05
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// {311153fb-d3f0-4ac6-b920-038de7cf5289}
|
||||
static constexpr GUID TelnetConnectionType = { 0x311153fb, 0xd3f0, 0x4ac6, { 0xb9, 0x20, 0x03, 0x8d, 0xe7, 0xcf, 0x52, 0x89 } };
|
|
@ -13,6 +13,7 @@
|
|||
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||
|
||||
#include "AzureCloudShellGenerator.h" // For AzureConnectionType
|
||||
#include "TelnetGenerator.h" // For TelnetConnectionType
|
||||
#include "TabRowControl.h"
|
||||
|
||||
using namespace winrt;
|
||||
|
@ -339,6 +340,10 @@ namespace winrt::TerminalApp::implementation
|
|||
newTabFlyout.Items().Append(separatorItem);
|
||||
|
||||
// add static items
|
||||
{
|
||||
const auto isUwp = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsUwp();
|
||||
|
||||
if (!isUwp)
|
||||
{
|
||||
// Create the settings button.
|
||||
auto settingsItem = WUX::Controls::MenuFlyoutItem{};
|
||||
|
@ -368,6 +373,7 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
feedbackFlyout.Click({ this, &TerminalPage::_FeedbackButtonOnClick });
|
||||
newTabFlyout.Items().Append(feedbackFlyout);
|
||||
}
|
||||
|
||||
// Create the about button.
|
||||
auto aboutFlyout = WUX::Controls::MenuFlyoutItem{};
|
||||
|
@ -527,6 +533,12 @@ namespace winrt::TerminalApp::implementation
|
|||
settings.InitialCols());
|
||||
}
|
||||
|
||||
else if (profile->HasConnectionType() &&
|
||||
profile->GetConnectionType() == TelnetConnectionType)
|
||||
{
|
||||
connection = TerminalConnection::TelnetConnection(settings.Commandline());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
auto conhostConn = TerminalConnection::ConptyConnection(settings.Commandline(),
|
||||
|
|
105
src/cascadia/TerminalApp/defaults-universal.json
Normal file
105
src/cascadia/TerminalApp/defaults-universal.json
Normal file
|
@ -0,0 +1,105 @@
|
|||
// THIS IS AN AUTO-GENERATED FILE! Changes to this file will be ignored.
|
||||
{
|
||||
"alwaysShowTabs": true,
|
||||
"defaultProfile": "{550ce7b8-d500-50ad-8a1a-c400c3262db3}",
|
||||
"initialCols": 120,
|
||||
"initialRows": 30,
|
||||
"requestedTheme": "system",
|
||||
"showTabsInTitlebar": false,
|
||||
"showTerminalTitleInTitlebar": true,
|
||||
"wordDelimiters": " /\\()\"'-.,:;<>~!@#$%^&*|+=[]{}~?\u2502",
|
||||
|
||||
"profiles":
|
||||
[
|
||||
{
|
||||
"guid": "{550ce7b8-d500-50ad-8a1a-c400c3262db3}",
|
||||
"name": "Telnet Loopback",
|
||||
"commandline": "ms-telnet-loop://127.0.0.1:23",
|
||||
"connectionType" : "{311153fb-d3f0-4ac6-b920-038de7cf5289}",
|
||||
"hidden": false,
|
||||
"startingDirectory": "%USERPROFILE%",
|
||||
"closeOnExit": "graceful",
|
||||
"colorScheme": "Vintage",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cursorShape": "bar",
|
||||
"icon": "ms-appx:///ProfileIcons/{550ce7b8-d500-50ad-8a1a-c400c3262db3}.png",
|
||||
"padding": "8, 8, 8, 8",
|
||||
"snapOnInput": true,
|
||||
"useAcrylic": false
|
||||
}
|
||||
],
|
||||
"schemes":
|
||||
[
|
||||
{
|
||||
"name": "Vintage",
|
||||
"foreground": "#C0C0C0",
|
||||
"background": "#000000",
|
||||
"black": "#000000",
|
||||
"red": "#800000",
|
||||
"green": "#008000",
|
||||
"yellow": "#808000",
|
||||
"blue": "#000080",
|
||||
"purple": "#800080",
|
||||
"cyan": "#008080",
|
||||
"white": "#C0C0C0",
|
||||
"brightBlack": "#808080",
|
||||
"brightRed": "#FF0000",
|
||||
"brightGreen": "#00FF00",
|
||||
"brightYellow": "#FFFF00",
|
||||
"brightBlue": "#0000FF",
|
||||
"brightPurple": "#FF00FF",
|
||||
"brightCyan": "#00FFFF",
|
||||
"brightWhite": "#FFFFFF"
|
||||
}
|
||||
],
|
||||
"keybindings":
|
||||
[
|
||||
{ "command": "closePane", "keys": [ "ctrl+shift+w" ] },
|
||||
{ "command": "closeWindow", "keys": [ "alt+f4" ] },
|
||||
{ "command": "copy", "keys": [ "ctrl+shift+c" ] },
|
||||
{ "command": "decreaseFontSize", "keys": [ "ctrl+-" ] },
|
||||
{ "command": "duplicateTab", "keys": [ "ctrl+shift+d" ] },
|
||||
{ "command": "increaseFontSize", "keys": [ "ctrl+=" ] },
|
||||
{ "command": { "action": "moveFocus", "direction": "down" }, "keys": [ "alt+down" ] },
|
||||
{ "command": { "action": "moveFocus", "direction": "left" }, "keys": [ "alt+left" ] },
|
||||
{ "command": { "action": "moveFocus", "direction": "right" }, "keys": [ "alt+right" ] },
|
||||
{ "command": { "action": "moveFocus", "direction": "up" }, "keys": [ "alt+up" ] },
|
||||
{ "command": "newTab", "keys": [ "ctrl+shift+t" ] },
|
||||
{ "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] },
|
||||
{ "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] },
|
||||
{ "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] },
|
||||
{ "command": { "action": "newTab", "index": 3 }, "keys": ["ctrl+shift+4"] },
|
||||
{ "command": { "action": "newTab", "index": 4 }, "keys": ["ctrl+shift+5"] },
|
||||
{ "command": { "action": "newTab", "index": 5 }, "keys": ["ctrl+shift+6"] },
|
||||
{ "command": { "action": "newTab", "index": 6 }, "keys": ["ctrl+shift+7"] },
|
||||
{ "command": { "action": "newTab", "index": 7 }, "keys": ["ctrl+shift+8"] },
|
||||
{ "command": { "action": "newTab", "index": 8 }, "keys": ["ctrl+shift+9"] },
|
||||
{ "command": "nextTab", "keys": [ "ctrl+tab" ] },
|
||||
{ "command": "openNewTabDropdown", "keys": [ "ctrl+shift+space" ] },
|
||||
{ "command": "openSettings", "keys": [ "ctrl+," ] },
|
||||
{ "command": "paste", "keys": [ "ctrl+shift+v" ] },
|
||||
{ "command": "prevTab", "keys": [ "ctrl+shift+tab" ] },
|
||||
{ "command": "resetFontSize", "keys": ["ctrl+0"]},
|
||||
{ "command": { "action": "resizePane", "direction": "down" }, "keys": [ "alt+shift+down" ] },
|
||||
{ "command": { "action": "resizePane", "direction": "left" }, "keys": [ "alt+shift+left" ] },
|
||||
{ "command": { "action": "resizePane", "direction": "right" }, "keys": [ "alt+shift+right" ] },
|
||||
{ "command": { "action": "resizePane", "direction": "up" }, "keys": [ "alt+shift+up" ] },
|
||||
{ "command": "scrollDown", "keys": [ "ctrl+shift+down" ] },
|
||||
{ "command": "scrollDownPage", "keys": [ "ctrl+shift+pgdn" ] },
|
||||
{ "command": "scrollUp", "keys": [ "ctrl+shift+up" ] },
|
||||
{ "command": "scrollUpPage", "keys": [ "ctrl+shift+pgup" ] },
|
||||
{ "command": { "action": "splitPane", "split": "horizontal"}, "keys": [ "alt+shift+-" ] },
|
||||
{ "command": { "action": "splitPane", "split": "vertical"}, "keys": [ "alt+shift+plus" ] },
|
||||
{ "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] },
|
||||
{ "command": { "action": "switchToTab", "index": 1 }, "keys": ["ctrl+alt+2"] },
|
||||
{ "command": { "action": "switchToTab", "index": 2 }, "keys": ["ctrl+alt+3"] },
|
||||
{ "command": { "action": "switchToTab", "index": 3 }, "keys": ["ctrl+alt+4"] },
|
||||
{ "command": { "action": "switchToTab", "index": 4 }, "keys": ["ctrl+alt+5"] },
|
||||
{ "command": { "action": "switchToTab", "index": 5 }, "keys": ["ctrl+alt+6"] },
|
||||
{ "command": { "action": "switchToTab", "index": 6 }, "keys": ["ctrl+alt+7"] },
|
||||
{ "command": { "action": "switchToTab", "index": 7 }, "keys": ["ctrl+alt+8"] },
|
||||
{ "command": { "action": "switchToTab", "index": 8 }, "keys": ["ctrl+alt+9"] },
|
||||
{ "command": "toggleFullscreen", "keys": [ "alt+enter" ] },
|
||||
{ "command": "toggleFullscreen", "keys": [ "f11" ] }
|
||||
]
|
||||
}
|
|
@ -10,14 +10,12 @@
|
|||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
|
||||
<!--
|
||||
DON'T REDIRECT OUR OUTPUT.
|
||||
Setting this will tell cppwinrt.build.post.props to copy our output from
|
||||
the default OutDir up one level, so the wapproj will be able to find it.
|
||||
-->
|
||||
<NoOutputRedirection>true</NoOutputRedirection>
|
||||
|
||||
<!--
|
||||
This is an override that, puzzlingly, _forces XBF (XAML binary) embedding_.
|
||||
We have to do this to overcome a layout issue in the WAP packaging project.
|
||||
|
@ -25,10 +23,8 @@
|
|||
-->
|
||||
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- HERE BE DRAGONS:
|
||||
|
@ -54,7 +50,6 @@
|
|||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="../App.base.h" />
|
||||
|
@ -86,27 +81,27 @@
|
|||
<ClInclude Include="../PowershellCoreProfileGenerator.h" />
|
||||
<ClInclude Include="../WslDistroGenerator.h" />
|
||||
<ClInclude Include="../AzureCloudShellGenerator.h" />
|
||||
<ClInclude Include="../TelnetGenerator.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="../ShortcutActionDispatch.h" >
|
||||
<ClInclude Include="../ShortcutActionDispatch.h">
|
||||
<DependentUpon>../ShortcutActionDispatch.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../ActionArgs.h" >
|
||||
<ClInclude Include="../ActionArgs.h">
|
||||
<DependentUpon>../ActionArgs.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../ActionAndArgs.h" >
|
||||
<ClInclude Include="../ActionAndArgs.h">
|
||||
<DependentUpon>../ActionArgs.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../AppKeyBindings.h" >
|
||||
<ClInclude Include="../AppKeyBindings.h">
|
||||
<DependentUpon>../AppKeyBindings.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../App.h" >
|
||||
<ClInclude Include="../App.h">
|
||||
<DependentUpon>../App.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../AppLogic.h" >
|
||||
<ClInclude Include="../AppLogic.h">
|
||||
<DependentUpon>../AppLogic.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
<ItemGroup>
|
||||
<ClCompile Include="../init.cpp" />
|
||||
|
@ -141,41 +136,39 @@
|
|||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../AppKeyBindings.cpp" >
|
||||
<ClCompile Include="../AppKeyBindings.cpp">
|
||||
<DependentUpon>../AppKeyBindings.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../ShortcutActionDispatch.cpp" >
|
||||
<ClCompile Include="../ShortcutActionDispatch.cpp">
|
||||
<DependentUpon>../ShortcutActionDispatch.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../ActionAndArgs.cpp" >
|
||||
<ClCompile Include="../ActionAndArgs.cpp">
|
||||
<DependentUpon>../ActionArgs.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../ActionArgs.cpp" >
|
||||
<ClCompile Include="../ActionArgs.cpp">
|
||||
<DependentUpon>../ActionArgs.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../App.cpp" >
|
||||
<ClCompile Include="../App.cpp">
|
||||
<DependentUpon>../App.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../AppActionHandlers.cpp" >
|
||||
<ClCompile Include="../AppActionHandlers.cpp">
|
||||
<DependentUpon>../App.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../AppLogic.cpp" >
|
||||
<ClCompile Include="../AppLogic.cpp">
|
||||
<DependentUpon>../AppLogic.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
|
||||
<!-- You _NEED_ to include this file and the jsoncpp IncludePath (below) if
|
||||
you want to use jsoncpp -->
|
||||
<ClCompile Include="$(OpenConsoleDir)\dep\jsoncpp\jsoncpp.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- If you add idl files here, make sure to include their implementation's
|
||||
header in TerminalApp.vcxproj (as well as in this file) -->
|
||||
<Midl Include="../App.idl" >
|
||||
<Midl Include="../App.idl">
|
||||
<DependentUpon>../App.xaml</DependentUpon>
|
||||
</Midl>
|
||||
<Midl Include="../ShortcutActionDispatch.idl" />
|
||||
|
@ -199,13 +192,11 @@
|
|||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Misc Files ======================== -->
|
||||
<ItemGroup>
|
||||
<PRIResource Include="../Resources/en-US/Resources.resw" />
|
||||
<None Include="../packages.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Project References ======================== -->
|
||||
<ItemGroup>
|
||||
<!--
|
||||
|
@ -214,59 +205,49 @@
|
|||
you also update all the consumers
|
||||
-->
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
|
||||
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
|
||||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
<!-- For whatever reason, we can't include the TerminalControl and
|
||||
TerminalSettings projects' winmds via project references. So we'll have to
|
||||
manually include the winmds as References below -->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- A small helper for paths to the compiled cppwinrt projects -->
|
||||
<_BinRoot Condition="'$(Platform)' != 'Win32'">$(OpenConsoleDir)$(Platform)\$(Configuration)\</_BinRoot>
|
||||
<_BinRoot Condition="'$(Platform)' == 'Win32'">$(OpenConsoleDir)$(Configuration)\</_BinRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- This is a hack to get the ARM64 CI build working. See
|
||||
https://github.com/Microsoft/msbuild/issues/3746 - it looks like MsBuild
|
||||
just has a bug in it.-->
|
||||
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>Warning</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Manually add references to each of our dependent winmds. Mark them as
|
||||
private=false and CopyLocalSatelliteAssemblies=false, so that we don't
|
||||
propogate them upwards (which can make referencing this project result in
|
||||
duplicate type definitions)-->
|
||||
|
||||
<Reference Include="Microsoft.Terminal.Settings">
|
||||
<HintPath>$(_BinRoot)TerminalSettings\Microsoft.Terminal.Settings.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</Reference>
|
||||
|
||||
<Reference Include="Microsoft.Terminal.TerminalConnection">
|
||||
<HintPath>$(_BinRoot)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</Reference>
|
||||
|
||||
<Reference Include="Microsoft.Terminal.TerminalControl">
|
||||
<HintPath>$(_BinRoot)TerminalControl\Microsoft.Terminal.TerminalControl.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</Reference>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ====================== Compiler & Linker Flags ===================== -->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
|
@ -279,11 +260,8 @@
|
|||
<AdditionalDependencies>WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- ========================= Globals ======================== -->
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<!-- Manually include MUX here, instead of importing its targets file. We need
|
||||
to reference its winmd, but very specifically with the
|
||||
CopyLocalSatelliteAssemblies and Private properties set to false, as to not
|
||||
|
@ -306,7 +284,6 @@
|
|||
</Reference>
|
||||
<ReferenceCopyLocalPaths Include="$(_MUXRoot)runtimes\win10-$(Native-Platform)\native\Microsoft.UI.Xaml.dll" />
|
||||
<ReferenceCopyLocalPaths Include="$(_MUXRoot)runtimes\win10-$(Native-Platform)\native\Microsoft.UI.Xaml.pri" />
|
||||
|
||||
<!-- Microsoft.UI.XAML.Application -->
|
||||
<Reference Include="$(_MUXAppRoot)lib\uap10.0\Microsoft.Toolkit.Win32.UI.XamlHost.winmd">
|
||||
<Implementation>Microsoft.Toolkit.Win32.UI.XamlHost.dll</Implementation>
|
||||
|
@ -318,7 +295,6 @@
|
|||
<ReferenceCopyLocalPaths Include="$(_MUXAppRoot)runtimes\win10-$(Native-Platform)\native\Microsoft.Toolkit.Win32.UI.XamlHost.*" />
|
||||
</ItemGroup>
|
||||
<!-- End MUX import -->
|
||||
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
|
@ -326,8 +302,6 @@
|
|||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.2.191203001-prerelease\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.2.191203001-prerelease\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
||||
<!--
|
||||
By default, the PRI file will contain resource paths beginning with the
|
||||
project name. Since we enabled XBF embedding, this *also* includes App.xbf.
|
||||
|
@ -347,22 +321,18 @@
|
|||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!-- This target will take our defaults.json and stamp it into a .h file that
|
||||
we can include in the code directly. This way, we don't need to worry about
|
||||
failing to load the default settings at runtime. -->
|
||||
<Target Name="_TerminalAppGenerateDefaultsH"
|
||||
Inputs="..\defaults.json"
|
||||
Outputs="Generated Files\defaults.h"
|
||||
BeforeTargets="BeforeClCompile">
|
||||
<Target Name="_TerminalAppGenerateDefaultsH" Inputs="..\defaults.json" Outputs="Generated Files\defaults.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile ..\defaults.json -OutPath '"Generated Files\defaults.h"' -VariableName DefaultJson" />
|
||||
</Target>
|
||||
<!-- A different set of defaults for Universal variant -->
|
||||
<Target Name="_TerminalAppGenerateDefaultsUniversalH" Inputs="..\defaults-universal.json" Outputs="Generated Files\defaults-universal.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile ..\defaults-universal.json -OutPath '"Generated Files\defaults-universal.h"' -VariableName DefaultUniversalJson" />
|
||||
</Target>
|
||||
<!-- Same as above, but for the default profiles.json template -->
|
||||
<Target Name="_TerminalAppGenerateUserSettingsH"
|
||||
Inputs="..\userDefaults.json"
|
||||
Outputs="Generated Files\userDefaults.h"
|
||||
BeforeTargets="BeforeClCompile">
|
||||
<Target Name="_TerminalAppGenerateUserSettingsH" Inputs="..\userDefaults.json" Outputs="Generated Files\userDefaults.h" BeforeTargets="BeforeClCompile">
|
||||
<Exec Command="powershell.exe -noprofile –ExecutionPolicy Unrestricted $(OpenConsoleDir)\tools\GenerateHeaderForJson.ps1 -JsonFile ..\userDefaults.json -OutPath '"Generated Files\userDefaults.h"' -VariableName UserSettingsJson" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// We have to define GSL here, not PCH
|
||||
// because TelnetConnection has a conflicting GSL implementation.
|
||||
#include <gsl/gsl>
|
||||
|
||||
#include "AzureConnection.h"
|
||||
#include "AzureClientID.h"
|
||||
#include <sstream>
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// We have to define GSL here, not PCH
|
||||
// because TelnetConnection has a conflicting GSL implementation.
|
||||
#include <gsl/gsl>
|
||||
|
||||
#include "ConptyConnection.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
|
|
@ -214,4 +214,7 @@
|
|||
<comment>The first argument is the hexadecimal error code. The second is the process name.
|
||||
If this resource spans multiple lines, it will not be displayed properly. Yeah.</comment>
|
||||
</data>
|
||||
<data name="TelnetInternetOrServerIssue" xml:space="preserve">
|
||||
<value>Could not connect to telnet server.</value>
|
||||
</data>
|
||||
</root>
|
315
src/cascadia/TerminalConnection/TelnetConnection.cpp
Normal file
315
src/cascadia/TerminalConnection/TelnetConnection.cpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TelnetConnection.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "TelnetConnection.g.cpp"
|
||||
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
|
||||
using namespace ::Microsoft::Console;
|
||||
|
||||
constexpr std::wstring_view telnetScheme = L"telnet";
|
||||
constexpr std::wstring_view msTelnetLoopbackScheme = L"ms-telnet-loop";
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
TelnetConnection::TelnetConnection(const hstring& uri) :
|
||||
_reader{ nullptr },
|
||||
_writer{ nullptr },
|
||||
_uri{ uri }
|
||||
{
|
||||
_session.install(_nawsServer);
|
||||
_nawsServer.activate([](auto&&) {});
|
||||
}
|
||||
|
||||
// Method description:
|
||||
// - ascribes to the ITerminalConnection interface
|
||||
// - creates the output thread
|
||||
void TelnetConnection::Start()
|
||||
try
|
||||
{
|
||||
// Create our own output handling thread
|
||||
// Each connection needs to make sure to drain the output from its backing host.
|
||||
_hOutputThread.reset(CreateThread(
|
||||
nullptr,
|
||||
0,
|
||||
[](LPVOID lpParameter) {
|
||||
auto pInstance = reinterpret_cast<TelnetConnection*>(lpParameter);
|
||||
return pInstance->_outputThread();
|
||||
},
|
||||
this,
|
||||
0,
|
||||
nullptr));
|
||||
|
||||
THROW_LAST_ERROR_IF_NULL(_hOutputThread);
|
||||
|
||||
_transitionToState(ConnectionState::Connecting);
|
||||
|
||||
// Set initial winodw title.
|
||||
_TerminalOutputHandlers(L"\x1b]0;Telnet\x7");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
}
|
||||
|
||||
// Method description:
|
||||
// - ascribes to the ITerminalConnection interface
|
||||
// - handles the different possible inputs in the different states
|
||||
// Arguments:
|
||||
// the user's input
|
||||
void TelnetConnection::WriteInput(hstring const& data)
|
||||
{
|
||||
if (!_isStateOneOf(ConnectionState::Connected, ConnectionState::Connecting))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto str = winrt::to_string(data);
|
||||
if (str.size() == 1 && str.at(0) == L'\r')
|
||||
{
|
||||
str = "\r\n";
|
||||
}
|
||||
|
||||
telnetpp::bytes bytes(reinterpret_cast<const uint8_t*>(str.data()), str.size());
|
||||
_session.send(bytes, [=](telnetpp::bytes data) {
|
||||
_socketSend(data);
|
||||
});
|
||||
}
|
||||
|
||||
// Method description:
|
||||
// - ascribes to the ITerminalConnection interface
|
||||
// - resizes the terminal
|
||||
// Arguments:
|
||||
// - the new rows/cols values
|
||||
void TelnetConnection::Resize(uint32_t rows, uint32_t columns)
|
||||
{
|
||||
if (_prevResize.has_value() && _prevResize.value().first == rows && _prevResize.value().second == columns)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prevResize.emplace(std::pair{ rows, columns });
|
||||
|
||||
_nawsServer.set_window_size(gsl::narrow<uint16_t>(columns),
|
||||
gsl::narrow<uint16_t>(rows),
|
||||
[=](telnetpp::subnegotiation sub) {
|
||||
_session.send(sub,
|
||||
[=](telnetpp::bytes data) {
|
||||
_socketBufferedSend(data);
|
||||
});
|
||||
_socketFlushBuffer();
|
||||
});
|
||||
}
|
||||
|
||||
// Method description:
|
||||
// - ascribes to the ITerminalConnection interface
|
||||
// - closes the socket connection and the output thread
|
||||
void TelnetConnection::Close()
|
||||
try
|
||||
{
|
||||
if (_transitionToState(ConnectionState::Closing))
|
||||
{
|
||||
_socket.Close();
|
||||
if (_hOutputThread)
|
||||
{
|
||||
// Tear down our output thread
|
||||
WaitForSingleObject(_hOutputThread.get(), INFINITE);
|
||||
_hOutputThread.reset();
|
||||
}
|
||||
|
||||
_transitionToState(ConnectionState::Closed);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
}
|
||||
|
||||
// Method description:
|
||||
// - this is the output thread, where we initiate the connection to the remote host
|
||||
// and establish a socket connection
|
||||
// Return value:
|
||||
// - return status
|
||||
DWORD TelnetConnection::_outputThread()
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_isStateOneOf(ConnectionState::Failed))
|
||||
{
|
||||
_TerminalOutputHandlers(RS_(L"TelnetInternetOrServerIssue") + L"\r\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
else if (_isStateAtOrBeyond(ConnectionState::Closing))
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
else if (_isStateOneOf(ConnectionState::Connecting))
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto uri = Windows::Foundation::Uri(_uri);
|
||||
const auto host = Windows::Networking::HostName(uri.Host());
|
||||
|
||||
bool autoLogin = false;
|
||||
// If we specified the special ms loopback scheme, then set autologin and proceed below.
|
||||
if (msTelnetLoopbackScheme == uri.SchemeName())
|
||||
{
|
||||
autoLogin = true;
|
||||
}
|
||||
// Otherwise, make sure we said telnet://, anything else is not supported here.
|
||||
else if (telnetScheme != uri.SchemeName())
|
||||
{
|
||||
THROW_HR(E_INVALIDARG);
|
||||
}
|
||||
|
||||
_socket.ConnectAsync(host, winrt::to_hstring(uri.Port())).get();
|
||||
_writer = Windows::Storage::Streams::DataWriter(_socket.OutputStream());
|
||||
_reader = Windows::Storage::Streams::DataReader(_socket.InputStream());
|
||||
_reader.InputStreamOptions(Windows::Storage::Streams::InputStreamOptions::Partial); // returns when 1 or more bytes ready.
|
||||
_transitionToState(ConnectionState::Connected);
|
||||
|
||||
if (autoLogin)
|
||||
{
|
||||
// Send newline to bypass User Name prompt.
|
||||
const auto newline = winrt::to_hstring("\r\n");
|
||||
WriteInput(newline);
|
||||
|
||||
// Wait for login.
|
||||
Sleep(1000);
|
||||
|
||||
// Send "cls" enter to clear the thing and just look like a prompt.
|
||||
const auto clearScreen = winrt::to_hstring("cls\r\n");
|
||||
WriteInput(clearScreen);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
}
|
||||
}
|
||||
else if (_isStateOneOf(ConnectionState::Connected))
|
||||
{
|
||||
// Read from socket
|
||||
const auto amountReceived = _socketReceive(_receiveBuffer);
|
||||
|
||||
_session.receive(
|
||||
telnetpp::bytes{ _receiveBuffer.data(), amountReceived },
|
||||
[=](telnetpp::bytes data,
|
||||
std::function<void(telnetpp::bytes)> const& send) {
|
||||
_applicationReceive(data, send);
|
||||
},
|
||||
[=](telnetpp::bytes data) {
|
||||
_socketSend(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// If the exception was thrown while we were already supposed to be closing, fine. We're closed.
|
||||
// This is because the socket got mad things were being torn down.
|
||||
if (_isStateAtOrBeyond(ConnectionState::Closing))
|
||||
{
|
||||
_transitionToState(ConnectionState::Closed);
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Call to buffer up bytes to send to the remote device.
|
||||
// - You must flush before they'll go out.
|
||||
// Arguments:
|
||||
// - data - View of bytes to be sent
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TelnetConnection::_socketBufferedSend(telnetpp::bytes data)
|
||||
{
|
||||
const uint8_t* first = data.data();
|
||||
const uint8_t* last = data.data() + data.size();
|
||||
const winrt::array_view<const uint8_t> arrayView(first, last);
|
||||
_writer.WriteBytes(arrayView);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Flushes any buffered bytes to the underlying socket
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
fire_and_forget TelnetConnection::_socketFlushBuffer()
|
||||
{
|
||||
co_await _writer.StoreAsync();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Used to send bytes into the socket to the remote device
|
||||
// Arguments:
|
||||
// - data - View of bytes to be sent
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TelnetConnection::_socketSend(telnetpp::bytes data)
|
||||
{
|
||||
_socketBufferedSend(data);
|
||||
_socketFlushBuffer();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Reads bytes from the socket into the given array.
|
||||
// Arguments:
|
||||
// - buffer - The array of bytes to use for storage
|
||||
// Return Value:
|
||||
// - The number of bytes actually read (less than or equal to input array size)
|
||||
size_t TelnetConnection::_socketReceive(gsl::span<telnetpp::byte> buffer)
|
||||
{
|
||||
const auto bytesLoaded = _reader.LoadAsync(gsl::narrow<uint32_t>(buffer.size())).get();
|
||||
|
||||
// winrt::array_view, despite having a pointer and size constructor
|
||||
// hides it as protected.
|
||||
// So we have to get first/last (even though cppcorechecks will be
|
||||
// mad at us for it) to use a public array_view constructor.
|
||||
// The WinRT team isn't fixing this because std::span is coming
|
||||
// soon and that will do it.
|
||||
// So just do this for now and suppress the warnings.
|
||||
const auto first = buffer.data();
|
||||
const auto last = first + bytesLoaded;
|
||||
const winrt::array_view<uint8_t> arrayView(first, last);
|
||||
_reader.ReadBytes(arrayView);
|
||||
return bytesLoaded;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Called by telnetpp framework when application data is received on the channel
|
||||
// In contrast, telnet metadata payload is consumed by telnetpp and not forwarded to us.
|
||||
// Arguments:
|
||||
// - data - The relevant application-level payload received
|
||||
// - send - A function where we can send a reply to given data immediately
|
||||
// in reaction to the received message.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TelnetConnection::_applicationReceive(telnetpp::bytes data,
|
||||
std::function<void(telnetpp::bytes)> const& /*send*/)
|
||||
{
|
||||
// Convert telnetpp bytes to standard string_view
|
||||
const auto stringView = std::string_view{ reinterpret_cast<const char*>(data.data()), gsl::narrow<size_t>(data.size()) };
|
||||
|
||||
// Convert to hstring
|
||||
const auto hstr = winrt::to_hstring(stringView);
|
||||
|
||||
// Pass the output to our registered event handlers
|
||||
_TerminalOutputHandlers(hstr);
|
||||
}
|
||||
}
|
72
src/cascadia/TerminalConnection/TelnetConnection.h
Normal file
72
src/cascadia/TerminalConnection/TelnetConnection.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TelnetConnection.g.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100)
|
||||
#pragma warning(disable : 4251)
|
||||
#include <telnetpp/core.hpp>
|
||||
#include <telnetpp/session.hpp>
|
||||
#include <telnetpp/options/naws/server.hpp>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include "winrt/Windows.Networking.Sockets.h"
|
||||
#include "winrt/Windows.Storage.Streams.h"
|
||||
|
||||
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||
#include "ConnectionStateHolder.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
struct TelnetConnection : TelnetConnectionT<TelnetConnection>, ConnectionStateHolder<TelnetConnection>
|
||||
{
|
||||
TelnetConnection(const hstring& uri);
|
||||
|
||||
void Start();
|
||||
void WriteInput(hstring const& data);
|
||||
void Resize(uint32_t rows, uint32_t columns);
|
||||
void Close();
|
||||
|
||||
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
|
||||
|
||||
private:
|
||||
hstring _uri;
|
||||
|
||||
void _applicationReceive(telnetpp::bytes data,
|
||||
std::function<void(telnetpp::bytes)> const& send);
|
||||
|
||||
void _socketBufferedSend(telnetpp::bytes data);
|
||||
fire_and_forget _socketFlushBuffer();
|
||||
void _socketSend(telnetpp::bytes data);
|
||||
size_t _socketReceive(gsl::span<telnetpp::byte> buffer);
|
||||
|
||||
telnetpp::session _session;
|
||||
// NAWS = Negotiation About Window Size
|
||||
telnetpp::options::naws::server _nawsServer;
|
||||
Windows::Networking::Sockets::StreamSocket _socket;
|
||||
Windows::Storage::Streams::DataWriter _writer;
|
||||
Windows::Storage::Streams::DataReader _reader;
|
||||
|
||||
std::optional<std::pair<uint32_t, uint32_t>> _prevResize;
|
||||
|
||||
static constexpr size_t _receiveBufferSize = 1024;
|
||||
std::array<telnetpp::byte, _receiveBufferSize> _receiveBuffer;
|
||||
|
||||
wil::unique_handle _hOutputThread;
|
||||
|
||||
DWORD _outputThread();
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::factory_implementation
|
||||
{
|
||||
struct TelnetConnection : TelnetConnectionT<TelnetConnection, implementation::TelnetConnection>
|
||||
{
|
||||
};
|
||||
}
|
14
src/cascadia/TerminalConnection/TelnetConnection.idl
Normal file
14
src/cascadia/TerminalConnection/TelnetConnection.idl
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ITerminalConnection.idl";
|
||||
|
||||
namespace Microsoft.Terminal.TerminalConnection
|
||||
{
|
||||
[default_interface]
|
||||
runtimeclass TelnetConnection : ITerminalConnection
|
||||
{
|
||||
TelnetConnection(String uri);
|
||||
};
|
||||
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
|
||||
<!--
|
||||
DON'T REDIRECT OUR OUTPUT.
|
||||
Setting this will tell cppwinrt.build.post.props to copy our output from
|
||||
|
@ -15,13 +14,13 @@
|
|||
-->
|
||||
<NoOutputRedirection>true</NoOutputRedirection>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AzureClientID.h" />
|
||||
<ClInclude Include="AzureConnection.h" />
|
||||
<ClInclude Include="AzureConnection.h">
|
||||
<DependentUpon>AzureConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ConptyConnection.h">
|
||||
<DependentUpon>ConptyConnection.idl</DependentUpon>
|
||||
|
@ -29,10 +28,15 @@
|
|||
<ClInclude Include="EchoConnection.h">
|
||||
<DependentUpon>EchoConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TelnetConnection.h">
|
||||
<DependentUpon>TelnetConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="init.cpp"/>
|
||||
<ClCompile Include="AzureConnection.cpp" />
|
||||
<ClCompile Include="init.cpp" />
|
||||
<ClCompile Include="AzureConnection.cpp">
|
||||
<DependentUpon>AzureConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
|
@ -43,18 +47,21 @@
|
|||
<DependentUpon>ConptyConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="TelnetConnection.cpp">
|
||||
<DependentUpon>TelnetConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ITerminalConnection.idl" />
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="TelnetConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources/en-US/Resources.resw" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Project References ======================== -->
|
||||
<ItemGroup>
|
||||
<!--
|
||||
|
@ -65,30 +72,27 @@
|
|||
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj">
|
||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||
</ProjectReference>
|
||||
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
|
||||
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
<ProjectReference Include="..\..\winconpty\lib\winconptylib.vcxproj">
|
||||
<Project>{58a03bb2-df5a-4b66-91a0-7ef3ba01269a}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\vcpkg-cpprestsdk.2.10.14\build\native\vcpkg-cpprestsdk.targets" Condition="Exists('..\..\..\packages\vcpkg-cpprestsdk.2.10.14\build\native\vcpkg-cpprestsdk.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\vcpkg-cpprestsdk.2.10.14\build\native\vcpkg-cpprestsdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\vcpkg-cpprestsdk.2.10.14\build\native\vcpkg-cpprestsdk.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\vcpkg-telnetpp.1.0.1\build\native\vcpkg-telnetpp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\vcpkg-telnetpp.1.0.1\build\native\vcpkg-telnetpp.targets'))" />
|
||||
</Target>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\conptylib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="..\..\..\packages\vcpkg-telnetpp.1.0.1\build\native\vcpkg-telnetpp.targets" Condition="Exists('..\..\..\packages\vcpkg-telnetpp.1.0.1\build\native\vcpkg-telnetpp.targets')" />
|
||||
</Project>
|
|
@ -18,18 +18,21 @@
|
|||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="AzureConnection.cpp" />
|
||||
<ClCompile Include="init.cpp" />
|
||||
<ClCompile Include="TelnetConnection.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="EchoConnection.h" />
|
||||
<ClInclude Include="AzureConnection.h" />
|
||||
<ClInclude Include="AzureClientID.h" />
|
||||
<ClInclude Include="TelnetConnection.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ITerminalConnection.idl" />
|
||||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="TelnetConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
|
||||
<package id="vcpkg-cpprestsdk" version="2.10.14" targetFramework="native" />
|
||||
<package id="vcpkg-telnetpp" version="1.0.1" targetFramework="native" />
|
||||
</packages>
|
|
@ -10,6 +10,8 @@
|
|||
// Needs to be defined or we get redeclaration errors
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#define BLOCK_GSL
|
||||
|
||||
#include <LibraryIncludes.h>
|
||||
|
||||
// Must be included before any WinRT headers.
|
||||
|
|
19
src/cascadia/WinRTUtils/WinRTUtils.vcxproj.filters
Normal file
19
src/cascadia/WinRTUtils/WinRTUtils.vcxproj.filters
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="ScopedResourceLoader.cpp" />
|
||||
<ClCompile Include="LibraryResources.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="inc\ScopedResourceLoader.h" />
|
||||
<ClInclude Include="inc\LibraryResources.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -43,5 +43,6 @@
|
|||
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<Capability Name="privateNetworkClientServer"/>
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
|
|
@ -59,8 +59,10 @@
|
|||
// GSL
|
||||
// Block GSL Multi Span include because it both has C++17 deprecated iterators
|
||||
// and uses the C-namespaced "max" which conflicts with Windows definitions.
|
||||
#ifndef BLOCK_GSL
|
||||
#define GSL_MULTI_SPAN_H
|
||||
#include <gsl/gsl>
|
||||
#endif
|
||||
|
||||
// CppCoreCheck
|
||||
#include <CppCoreCheck/Warnings.h>
|
||||
|
|
Loading…
Reference in a new issue