Eric Bower
·
2025-05-24
pty.go
1package pssh
2
3import (
4 "encoding/binary"
5 "fmt"
6 "time"
7)
8
9func SessionMessage(sesh *SSHServerConnSession, msg string) {
10 _, _ = sesh.Write([]byte(msg + "\r\n"))
11}
12
13func DeprecatedNotice() SSHServerMiddleware {
14 return func(next SSHServerHandler) SSHServerHandler {
15 return func(sesh *SSHServerConnSession) error {
16 msg := fmt.Sprintf(
17 "%s\r\n\r\nRun %s to access pico's TUI",
18 "DEPRECATED",
19 "ssh pico.sh",
20 )
21 SessionMessage(sesh, msg)
22 return next(sesh)
23 }
24 }
25}
26
27func PtyMdw(mdw SSHServerMiddleware, waitTimeout time.Duration) SSHServerMiddleware {
28 return func(next SSHServerHandler) SSHServerHandler {
29 return func(sesh *SSHServerConnSession) error {
30 if waitTimeout > 0 {
31 afterTime := time.Now().Add(waitTimeout)
32
33 for time.Now().After(afterTime) {
34 _, _, ok := sesh.Pty()
35 if ok {
36 break
37 }
38
39 time.Sleep(50 * time.Millisecond)
40 }
41 }
42
43 _, _, ok := sesh.Pty()
44 if !ok {
45 return next(sesh)
46 }
47 return mdw(next)(sesh)
48 }
49 }
50}
51
52type Window struct {
53 Width int
54 Height int
55 HeightPixels int
56 WidthPixels int
57}
58
59type Pty struct {
60 Term string
61 Window Window
62}
63
64func (p *Pty) Resize(width, height int) error {
65 return nil
66}
67
68func (p *Pty) Name() string {
69 return ""
70}
71
72func parsePtyRequest(s []byte) (pty Pty, ok bool) {
73 term, s, ok := parseString(s)
74 if !ok {
75 return
76 }
77 width32, s, ok := parseUint32(s)
78 if !ok {
79 return
80 }
81 height32, _, ok := parseUint32(s)
82 if !ok {
83 return
84 }
85 pty = Pty{
86 Term: term,
87 Window: Window{
88 Width: int(width32),
89 Height: int(height32),
90 },
91 }
92 return
93}
94
95func parseWinchRequest(s []byte) (win Window, ok bool) {
96 width32, s, ok := parseUint32(s)
97 if width32 < 1 {
98 ok = false
99 }
100 if !ok {
101 return
102 }
103 height32, _, ok := parseUint32(s)
104 if height32 < 1 {
105 ok = false
106 }
107 if !ok {
108 return
109 }
110 win = Window{
111 Width: int(width32),
112 Height: int(height32),
113 }
114 return
115}
116
117func parseString(in []byte) (out string, rest []byte, ok bool) {
118 if len(in) < 4 {
119 return
120 }
121 length := binary.BigEndian.Uint32(in)
122 if uint32(len(in)) < 4+length {
123 return
124 }
125 out = string(in[4 : 4+length])
126 rest = in[4+length:]
127 ok = true
128 return
129}
130
131func parseUint32(in []byte) (uint32, []byte, bool) {
132 if len(in) < 4 {
133 return 0, nil, false
134 }
135 return binary.BigEndian.Uint32(in), in[4:], true
136}