-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcons.go
140 lines (118 loc) · 3.42 KB
/
cons.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/abakum/go-ser2net/pkg/ser2net"
)
// Подключаем консоль Serial к сессии ssh или локально через s.
// Завершение сессии через `<Enter>~.`
func cons(ctx context.Context, s io.ReadWriteCloser, Serial, Baud, exit string, println ...func(v ...any)) (err error) {
if Serial == "" {
return ErrNotFoundFreeSerial
}
print := func(a ...any) {
for _, p := range println {
p(a...)
}
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
w, _ := ser2net.NewSerialWorker(ctx, Serial, ser2net.BaudRate(strconv.Atoi(Baud)))
defer w.Stop()
go w.Worker()
c, err := w.NewIoReadWriteCloser()
if err != nil {
return err
}
defer c.Close()
chanByte := make(chan byte, B16)
// t := time.AfterFunc(time.Millisecond*time.Duration(ser2net.TOopen), func() {
t := time.AfterFunc(time.Second, func() {
SetMode(w, ctx, nil, chanByte, EED+exit, 0, println...)
w.Stop()
})
defer t.Stop()
ss := "Serial"
sp := Serial
if strings.Contains(w.String(), "$") {
// Команда или интерпретатор.
Serial = ""
// println[0](mess(quit, w.String()))
ss = "Command"
} else {
if !ser2net.SerialPath(Serial) {
ss = "Connection"
}
// time.AfterFunc(time.Second, func() { println[0](mess(quit, w.String())) })
}
defer func() {
print(ss, sp, "closed", w.SerialClose(), w)
}()
go w.CopyCancel(s, c)
_, err = w.CancelCopy(newSideWriter(c, args.EscapeChar, Serial, chanByte), s)
return
}
// Web сервер ждёт на порту web.
// SetMode использует r или chanByte для смены serial.Mode порта Serial.
// На консоль клиента println[0] выводит протокол через ssh канал.
// Локально println[1] выводит протокол.
func s2w(ctx context.Context, r io.Reader, chanB chan byte, Serial, host string, wp int, Baud, exit string, println ...func(v ...any)) error {
if Serial == "" {
return ErrNotFoundFreeSerial
}
w, _ := ser2net.NewSerialWorker(ctx, Serial, ser2net.BaudRate(strconv.Atoi(Baud)))
defer w.Stop()
go w.Worker()
// t := time.AfterFunc(time.Millisecond*time.Duration(ser2net.TOopen), func() {
t := time.AfterFunc(time.Second, func() {
SetMode(w, ctx, r, chanB, exit, wp, println...)
w.Stop()
})
defer t.Stop()
hp := newHostPort(host, wp, Serial)
defer hp.remove()
hp.write()
return w.StartGoTTY(host, wp, "", false)
}
type hostPort struct {
Host string `json:"host"`
Port int `json:"port"`
Path string `json:"path"`
}
func newHostPort(host string, port int, path string) hostPort {
os.MkdirAll(tmp, DIRMODE)
return hostPort{ser2net.LocalPort(host), port, path}
}
func (hp *hostPort) read() (err error) {
bytes, err := os.ReadFile(hp.name())
if err != nil {
return
}
return json.Unmarshal(bytes, hp)
}
func (hp *hostPort) write() (err error) {
bytes, err := json.Marshal(hp)
if err != nil {
return
}
return os.WriteFile(hp.name(), bytes, FILEMODE)
}
func (hp *hostPort) dest() string {
return JoinHostPort(hp.Host, hp.Port)
}
func (hp *hostPort) name() string {
return filepath.Join(tmp, fmt.Sprintf("%s_%d.json", hp.Host, hp.Port))
}
func (hp *hostPort) String() string {
return fmt.Sprintf("start http://%s:%d %s", hp.Host, hp.Port, hp.Path)
}
func (hp *hostPort) remove() (err error) {
return os.Remove(hp.name())
}