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
package proxy
import (
"context"
"fmt"
"sync"
"time"
"github.com/ibuler/ssh"
"cocogo/pkg/logger"
)
type Switch struct {
Id string `json:"id"`
User string `json:"user"`
Asset string `json:"asset"`
SystemUser string `json:"system_user"`
Org string `json:"org_id"`
LoginFrom string `json:"login_from"`
RemoteAddr string `json:"remote_addr"`
DateStart time.Time `json:"date_start"`
DateEnd time.Time `json:"date_end"`
DateActive time.Time `json:"date_last_active"`
Finished bool `json:"is_finished"`
Closed bool
parser *Parser
userSession ssh.Session
serverConn ServerConnection
closeChan chan struct{}
}
func (s *Switch) preBridge() {
}
func (s *Switch) postBridge() {
}
func (s *Switch) watchWindowChange(ctx context.Context, winCh <-chan ssh.Window, wg *sync.WaitGroup) {
defer wg.Done()
defer func() {
logger.Debug("Watch window change routine end")
}()
for {
select {
case <-ctx.Done():
return
case win, ok := <-winCh:
if !ok {
return
}
err := s.serverConn.SetWinSize(win.Height, win.Width)
if err != nil {
logger.Error("Change server win size err: ", err)
return
}
logger.Debugf("Window server change: %d*%d", win.Height, win.Width)
}
}
}
func (s *Switch) readUserToServer(wg *sync.WaitGroup) {
defer wg.Done()
defer func() {
logger.Debug("Read user to server end")
}()
buf := make([]byte, 1024)
writer := s.serverConn.Writer()
for {
nr, err := s.userSession.Read(buf)
if err != nil {
return
}
buf2 := s.parser.ParseUserInput(buf[:nr])
_, err = writer.Write(buf2)
if err != nil {
return
}
}
}
func (s *Switch) readServerToUser(wg *sync.WaitGroup) {
defer wg.Done()
defer func() {
logger.Debug("Read server to user end")
}()
buf := make([]byte, 1024)
reader := s.serverConn.Reader()
for {
nr, err := reader.Read(buf)
if err != nil {
logger.Errorf("Read from server error: %s", err)
break
}
buf2 := s.parser.ParseServerOutput(buf[:nr])
_, err = s.userSession.Write(buf2)
if err != nil {
break
}
}
}
func (s *Switch) Bridge(ctx context.Context) (err error) {
_, winCh, _ := s.userSession.Pty()
wg := sync.WaitGroup{}
wg.Add(3)
go s.watchWindowChange(ctx, winCh, &wg)
go s.readUserToServer(&wg)
go s.readServerToUser(&wg)
wg.Wait()
fmt.Println("Bride end")
return
}