-
Notifications
You must be signed in to change notification settings - Fork 467
/
shell.go
127 lines (113 loc) · 2.67 KB
/
shell.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
package shell
import (
"fmt"
"net"
"net/http"
"sync"
"time"
"github.com/lwch/logging"
"github.com/lwch/natpass/code/client/conn"
"github.com/lwch/natpass/code/client/global"
"github.com/lwch/natpass/code/client/rule"
"github.com/lwch/runtime"
)
// Shell shell handler
type Shell struct {
sync.RWMutex
Name string
cfg global.Rule
links map[string]*Link
readTimeout time.Duration
writeTimeout time.Duration
}
// New new shell
func New(cfg global.Rule, readTimeout, writeTimeout time.Duration) *Shell {
return &Shell{
Name: cfg.Name,
cfg: cfg,
links: make(map[string]*Link),
readTimeout: readTimeout,
writeTimeout: writeTimeout,
}
}
// NewLink new link
func (shell *Shell) NewLink(id, remote string, localConn net.Conn, remoteConn *conn.Conn) rule.Link {
remoteConn.AddLink(id)
link := &Link{
parent: shell,
id: id,
target: remote,
remote: remoteConn,
}
shell.Lock()
shell.links[link.id] = link
shell.Unlock()
return link
}
// GetName get shell rule name
func (shell *Shell) GetName() string {
return shell.Name
}
// GetTypeName get shell rule type name
func (shell *Shell) GetTypeName() string {
return "shell"
}
// GetTarget get target of this rule
func (shell *Shell) GetTarget() string {
return shell.cfg.Target
}
// GetLinks get rule links
func (shell *Shell) GetLinks() []rule.Link {
ret := make([]rule.Link, 0, len(shell.links))
shell.RLock()
for _, link := range shell.links {
ret = append(ret, link)
}
shell.RUnlock()
return ret
}
// GetRemote get remote target name
func (shell *Shell) GetRemote() string {
return shell.cfg.Target
}
// GetPort get listen port
func (shell *Shell) GetPort() uint16 {
return shell.cfg.LocalPort
}
// OnDisconnect on disconnect message
func (shell *Shell) OnDisconnect(id string) {
shell.RLock()
link := shell.links[id]
shell.RUnlock()
if link != nil {
link.Close(false)
}
}
// Handle handle shell
func (shell *Shell) Handle(c *conn.Conn) {
defer func() {
if err := recover(); err != nil {
logging.Error("close shell: %s, err=%v", shell.Name, err)
}
}()
pf := func(cb func(*conn.Conn, http.ResponseWriter, *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cb(c, w, r)
}
}
mux := http.NewServeMux()
mux.HandleFunc("/new", pf(shell.New))
mux.HandleFunc("/ws/", pf(shell.WS))
mux.HandleFunc("/resize", pf(shell.Resize))
mux.HandleFunc("/", shell.Render)
svr := &http.Server{
Addr: fmt.Sprintf("%s:%d", shell.cfg.LocalAddr, shell.cfg.LocalPort),
Handler: mux,
}
runtime.Assert(svr.ListenAndServe())
}
func (shell *Shell) remove(id string) {
shell.Lock()
delete(shell.links, id)
shell.Unlock()
}