Public Access
Add port forwarding: local, remote and dynamic, per terminal session
A host can now carry port forwards (-L, -R, -D), saved inside its encrypted payload as RelayTicketRequest.PortForwardId already assumed, so they sync and merge per forward like tags and pinned paths. The host schema moves to version 8 only for hosts that carry forwards. ISshConnection gains StartForwardAsync over SSH.NET's forwarded ports. Every listener binds loopback and there is no bind-address field: a forward is something any member of a shared keychain can edit. A remote forward's target is resolved here, IPv4 first, rather than by SSH.NET's constructor, which takes the first DNS answer and can send ::1. Forwards start with every terminal opened to the host and stop with its connection; a reconnect starts them again. The session sidebar lists them with state, failure reason and an on/off switch, the status bar counts the listening ones, and the host editor and detail pane gain a PORT FORWARDS section. A forward that cannot start fails alone. The phone does not start forwards yet: it has no surface showing what is listening, and its More screen now says so. No byte counts, since SSH.NET keeps none.
This commit is contained in:
1 parent
c8848ec1e3
commit
f05deb4fbc
36 files changed
+2776
-42
No files matched your search
@@ -39,6 +39,22 @@
|
||||
is showing without knowing anything about the state — and the pane beside it grows into what is freed.
|
||||
-->
|
||||
|
||||
<!--
|
||||
A forward's state word: green only while it is listening, which is the one status Live is for, and the
|
||||
danger text colour for a forward that could not start. OFF and STARTING stay faint.
|
||||
-->
|
||||
<UserControl.Styles>
|
||||
<Style Selector="TextBlock.fwdstate">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.fwdstate.live">
|
||||
<Setter Property="Foreground" Value="{StaticResource Live}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.fwdstate.failed">
|
||||
<Setter Property="Foreground" Value="{StaticResource DangerText}" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<Panel>
|
||||
|
||||
<!-- ============ THE RAIL, WHEN THE COLUMN IS CLOSED ============ -->
|
||||
@@ -142,6 +158,64 @@
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<!-- ============ FORWARDS (the terminal surface only) ============ -->
|
||||
<!--
|
||||
The selected tab's forwards: the host's saved ones, as they run over this session. Each row is
|
||||
its own switch, and a failed one says why under its notation — a port already taken, most often
|
||||
by a second tab to the same host running the same forwards. Nothing here edits a forward; the add
|
||||
row goes to the host's editor, where they are saved, as Pin folder does for QUICK ACCESS.
|
||||
|
||||
No byte counts, which the design draws. SSH.NET keeps no count of what a forward carries, so a
|
||||
number here would be invented.
|
||||
-->
|
||||
<StackPanel Spacing="6" Margin="0,16,0,0" IsVisible="{Binding #Root.ShowsForwards}">
|
||||
|
||||
<TextBlock Classes="label" Text="FORWARDS" FontSize="10" Margin="8,0" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding SelectedTab.Forwards}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:PortForwardViewModel">
|
||||
<!--
|
||||
The reason sits under the row rather than inside it: a sidebar row is a fixed 33 pixels, and
|
||||
a refusal is a sentence. Indented to the notation, so it reads as belonging to the row.
|
||||
-->
|
||||
<StackPanel>
|
||||
<Button Classes="sidebarrow" Command="{Binding ToggleCommand}"
|
||||
ToolTip.Tip="{Binding Route}">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<TextBlock Grid.Column="0" Text=""
|
||||
FontFamily="{StaticResource IconFont}" FontSize="15"
|
||||
Foreground="{StaticResource AccentText}" VerticalAlignment="Center"
|
||||
Margin="0,0,10,0" />
|
||||
<TextBlock Grid.Column="1" FontFamily="{StaticResource MonoFont}" FontSize="12.5"
|
||||
Text="{Binding Notation}" TextTrimming="CharacterEllipsis"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Classes="fwdstate" FontFamily="Montserrat"
|
||||
FontWeight="SemiBold" FontSize="9" LetterSpacing="1"
|
||||
VerticalAlignment="Center" Margin="8,0,0,0"
|
||||
Text="{Binding StateText}"
|
||||
Classes.live="{Binding IsListening}" Classes.failed="{Binding IsFailed}" />
|
||||
</Grid>
|
||||
</Button>
|
||||
<TextBlock FontSize="11" Foreground="{StaticResource TextFaint}" TextWrapping="Wrap"
|
||||
Margin="37,0,12,4" Text="{Binding Detail}"
|
||||
IsVisible="{Binding Detail, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Button Classes="sidebaradd" Command="{Binding AddForwardFromSidebarCommand}"
|
||||
ToolTip.Tip="Opens the active tab's host for editing, where its forwards are saved. A new forward starts with the next connection.">
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<TextBlock Text="" FontFamily="{StaticResource IconFont}" FontSize="14"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock Text="Add forward" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!-- ============ SNIPS (the terminal surface only) ============ -->
|
||||
<StackPanel Spacing="6" Margin="0,16,0,0" IsVisible="{Binding #Root.ShowsSnips}">
|
||||
|
||||
|
||||
Reference in new issue
Block a user