Antonio Mika
·
2025-04-10
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 {
34 if time.Now().After(afterTime) {
35 break
36 }
37
38 _, _, ok := sesh.Pty()
39 if ok {
40 break
41 }
42
43 time.Sleep(50 * time.Millisecond)
44 }
45 }
46
47 _, _, ok := sesh.Pty()
48 if !ok {
49 return next(sesh)
50 }
51 return mdw(next)(sesh)
52 }
53 }
54}
55
56type Window struct {
57 Width int
58 Height int
59 HeightPixels int
60 WidthPixels int
61}
62
63type Pty struct {
64 Term string
65 Window Window
66}
67
68func (p *Pty) Resize(width, height int) error {
69 return nil
70}
71
72func (p *Pty) Name() string {
73 return ""
74}
75
76func parsePtyRequest(s []byte) (pty Pty, ok bool) {
77 term, s, ok := parseString(s)
78 if !ok {
79 return
80 }
81 width32, s, ok := parseUint32(s)
82 if !ok {
83 return
84 }
85 height32, _, ok := parseUint32(s)
86 if !ok {
87 return
88 }
89 pty = Pty{
90 Term: term,
91 Window: Window{
92 Width: int(width32),
93 Height: int(height32),
94 },
95 }
96 return
97}
98
99func parseWinchRequest(s []byte) (win Window, ok bool) {
100 width32, s, ok := parseUint32(s)
101 if width32 < 1 {
102 ok = false
103 }
104 if !ok {
105 return
106 }
107 height32, _, ok := parseUint32(s)
108 if height32 < 1 {
109 ok = false
110 }
111 if !ok {
112 return
113 }
114 win = Window{
115 Width: int(width32),
116 Height: int(height32),
117 }
118 return
119}
120
121func parseString(in []byte) (out string, rest []byte, ok bool) {
122 if len(in) < 4 {
123 return
124 }
125 length := binary.BigEndian.Uint32(in)
126 if uint32(len(in)) < 4+length {
127 return
128 }
129 out = string(in[4 : 4+length])
130 rest = in[4+length:]
131 ok = true
132 return
133}
134
135func parseUint32(in []byte) (uint32, []byte, bool) {
136 if len(in) < 4 {
137 return 0, nil, false
138 }
139 return binary.BigEndian.Uint32(in), in[4:], true
140}