-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathproxy.go
More file actions
114 lines (97 loc) · 2.26 KB
/
proxy.go
File metadata and controls
114 lines (97 loc) · 2.26 KB
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
package vncproxy
import (
"net/http"
"strings"
"sync"
"time"
"golang.org/x/net/websocket"
)
type TokenHandler func(r *http.Request) (addr string, err error)
// Config represents vnc proxy config
type Config struct {
LogLevel uint32
Logger Logger
DialTimeout time.Duration
TokenHandler
}
// Proxy represents vnc proxy
type Proxy struct {
logLevel uint32
logger *logger
dialTimeout time.Duration // Timeout for connecting to each target vnc server
peers map[*peer]struct{}
l sync.RWMutex
tokenHandler TokenHandler
}
// New returns a vnc proxy
// If token handler is nil, vnc backend address will always be :5901
func New(conf *Config) *Proxy {
if conf.TokenHandler == nil {
conf.TokenHandler = func(r *http.Request) (addr string, err error) {
return ":5901", nil
}
}
return &Proxy{
logLevel: conf.LogLevel,
logger: NewLogger(conf.LogLevel, conf.Logger),
dialTimeout: conf.DialTimeout,
peers: make(map[*peer]struct{}),
l: sync.RWMutex{},
tokenHandler: conf.TokenHandler,
}
}
// ServeWS provides websocket handler
func (p *Proxy) ServeWS(ws *websocket.Conn) {
p.logger.Debugf("ServeWS")
ws.PayloadType = websocket.BinaryFrame
r := ws.Request()
p.logger.Debugf("request url: %v", r.URL)
// get vnc backend server addr
addr, err := p.tokenHandler(r)
if err != nil {
p.logger.Infof("get vnc backend failed: %v", err)
return
}
peer, err := NewPeer(ws, addr, p.dialTimeout)
if err != nil {
p.logger.Infof("new vnc peer failed: %v", err)
return
}
p.addPeer(peer)
defer func() {
p.logger.Info("close peer")
p.deletePeer(peer)
}()
go func() {
if err := peer.ReadTarget(); err != nil {
if strings.Contains(err.Error(), "use of closed network connection") {
return
}
p.logger.Info(err)
return
}
}()
if err = peer.ReadSource(); err != nil {
if strings.Contains(err.Error(), "use of closed network connection") {
return
}
p.logger.Info(err)
return
}
}
func (p *Proxy) addPeer(peer *peer) {
p.l.Lock()
p.peers[peer] = struct{}{}
p.l.Unlock()
}
func (p *Proxy) deletePeer(peer *peer) {
p.l.Lock()
delete(p.peers, peer)
peer.Close()
p.l.Unlock()
}
func (p *Proxy) Peers() map[*peer]struct{} {
p.l.RLock()
defer p.l.RUnlock()
return p.peers
}