2 Commits
6 changed files with 24 additions and 31 deletions
+2 -1
View File
@@ -158,7 +158,8 @@ func (s *session) recvLoop() {
t := s.client.Transport()
oldNum := t.LastRecvOldNum()
newNum := t.LastRecvNewNum()
s.tracker.applyDiff(diff, oldNum, newNum)
throwawayNum := t.ThrowawayNum()
s.tracker.applyDiff(diff, oldNum, newNum, throwawayNum)
}
}
+9 -25
View File
@@ -41,7 +41,8 @@ func newStateTracker(cols, rows int) *stateTracker {
}
// applyDiff processes an incoming server diff using state tracking.
func (st *stateTracker) applyDiff(diff []byte, oldNum, newNum uint64) {
// throwawayNum is the server's indication of which states it no longer references.
func (st *stateTracker) applyDiff(diff []byte, oldNum, newNum, throwawayNum uint64) {
st.mu.Lock()
defer st.mu.Unlock()
@@ -93,9 +94,13 @@ func (st *stateTracker) applyDiff(diff []byte, oldNum, newNum uint64) {
st.latestState = newNum
}
// Bound states list.
if len(st.states) > 128 {
st.pruneStates()
// Prune states the server no longer references.
if throwawayNum > 0 {
for n := range st.states {
if n < throwawayNum {
delete(st.states, n)
}
}
}
// Display diff: compute ANSI difference between displayed and latest.
@@ -133,24 +138,3 @@ func (st *stateTracker) resize(cols, rows int) {
st.displayedFB = nil
}
func (st *stateTracker) pruneStates() {
if len(st.states) <= 64 {
return
}
// Keep the 64 most recent states.
var nums []uint64
for n := range st.states {
nums = append(nums, n)
}
// Simple sort for small lists.
for i := range nums {
for j := i + 1; j < len(nums); j++ {
if nums[j] < nums[i] {
nums[i], nums[j] = nums[j], nums[i]
}
}
}
for _, n := range nums[:len(nums)-64] {
delete(st.states, n)
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ go 1.26.0
require (
github.com/charmbracelet/x/ansi v0.11.6
github.com/creack/pty v1.1.24
github.com/unixshells/vt-go v0.1.0
github.com/unixshells/vt-go v0.2.0
golang.org/x/crypto v0.49.0
golang.org/x/term v0.41.0
)
+2 -2
View File
@@ -28,8 +28,8 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/unixshells/vt-go v0.1.0 h1:HWILcExV8MHc6o2YqIRMIM/KrjH31kPzZrlvLS9BG6Y=
github.com/unixshells/vt-go v0.1.0/go.mod h1:dZpOXxVyO7LG1uxkVMixX7HwUf2ZbUkEKhtHHJTTIBI=
github.com/unixshells/vt-go v0.2.0 h1:fKOHymso7q4mE/TTRPBZMWtM5kZFoHdPUsk1kkLtypA=
github.com/unixshells/vt-go v0.2.0/go.mod h1:dZpOXxVyO7LG1uxkVMixX7HwUf2ZbUkEKhtHHJTTIBI=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
+2 -2
View File
@@ -150,7 +150,7 @@ func (s *Server) Serve() error {
Cols: uint16(s.cols),
})
s.emu = vt.NewEmulator(s.cols, s.rows)
s.emu = vt.NewEmulatorNoScrollback(s.cols, s.rows)
s.curVisible.Store(true)
s.emu.SetCallbacks(vt.Callbacks{
CursorVisibility: func(visible bool) { s.curVisible.Store(visible) },
@@ -199,7 +199,7 @@ func (s *Server) Done() <-chan struct{} {
func (s *Server) ServeRW(rw io.ReadWriteCloser, resize func(cols, rows uint16)) error {
close(s.started)
s.emu = vt.NewEmulator(s.cols, s.rows)
s.emu = vt.NewEmulatorNoScrollback(s.cols, s.rows)
s.curVisible.Store(true)
s.emu.SetCallbacks(vt.Callbacks{
CursorVisibility: func(visible bool) { s.curVisible.Store(visible) },
+8
View File
@@ -379,6 +379,14 @@ func (t *Transport) LastRecvNewNum() uint64 {
return t.lastRecvNewNum
}
// ThrowawayNum returns the server's throwaway number — states below this
// are no longer referenced by the server and can be safely pruned.
func (t *Transport) ThrowawayNum() uint64 {
t.mu.Lock()
defer t.mu.Unlock()
return t.throwawayNum
}
// LastRecv returns the time of the last received datagram.
func (t *Transport) LastRecv() time.Time {
t.mu.Lock()