-
Notifications
You must be signed in to change notification settings - Fork 80
/
Copy pathterminal.go
80 lines (73 loc) · 1.41 KB
/
terminal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package kvm
import (
"encoding/json"
"io"
"os"
"os/exec"
"github.com/creack/pty"
"github.com/pion/webrtc/v4"
)
type TerminalSize struct {
Rows int `json:"rows"`
Cols int `json:"cols"`
}
func handleTerminalChannel(d *webrtc.DataChannel) {
var ptmx *os.File
var cmd *exec.Cmd
d.OnOpen(func() {
cmd = exec.Command("/bin/sh")
var err error
ptmx, err = pty.Start(cmd)
if err != nil {
logger.Errorf("Failed to start pty: %v", err)
d.Close()
return
}
go func() {
buf := make([]byte, 1024)
for {
n, err := ptmx.Read(buf)
if err != nil {
if err != io.EOF {
logger.Errorf("Failed to read from pty: %v", err)
}
break
}
err = d.Send(buf[:n])
if err != nil {
logger.Errorf("Failed to send pty output: %v", err)
break
}
}
}()
})
d.OnMessage(func(msg webrtc.DataChannelMessage) {
if ptmx == nil {
return
}
if msg.IsString {
var size TerminalSize
err := json.Unmarshal([]byte(msg.Data), &size)
if err == nil {
pty.Setsize(ptmx, &pty.Winsize{
Rows: uint16(size.Rows),
Cols: uint16(size.Cols),
})
return
}
logger.Errorf("Failed to parse terminal size: %v", err)
}
_, err := ptmx.Write(msg.Data)
if err != nil {
logger.Errorf("Failed to write to pty: %v", err)
}
})
d.OnClose(func() {
if ptmx != nil {
ptmx.Close()
}
if cmd != nil && cmd.Process != nil {
cmd.Process.Kill()
}
})
}