forked from p4gefau1t/trojan-go
-
Notifications
You must be signed in to change notification settings - Fork 1
/
client.go
65 lines (57 loc) · 1.67 KB
/
client.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
package websocket
import (
"context"
"strings"
"golang.org/x/net/websocket"
"github.com/faireal/trojan-go/common"
"github.com/faireal/trojan-go/config"
"github.com/faireal/trojan-go/log"
"github.com/faireal/trojan-go/tunnel"
)
type Client struct {
underlay tunnel.Client
hostname string
path string
}
func (c *Client) DialConn(*tunnel.Address, tunnel.Tunnel) (tunnel.Conn, error) {
conn, err := c.underlay.DialConn(nil, &Tunnel{})
if err != nil {
return nil, common.NewError("websocket cannot dial with underlying client").Base(err)
}
url := "wss://" + c.hostname + c.path
origin := "https://" + c.hostname
wsConfig, err := websocket.NewConfig(url, origin)
if err != nil {
return nil, common.NewError("invalid websocket config").Base(err)
}
wsConn, err := websocket.NewClient(wsConfig, conn)
if err != nil {
return nil, common.NewError("websocket failed to handshake with server").Base(err)
}
return &OutboundConn{
Conn: wsConn,
tcpConn: conn,
}, nil
}
func (c *Client) DialPacket(tunnel.Tunnel) (tunnel.PacketConn, error) {
return nil, common.NewError("not supported by websocket")
}
func (c *Client) Close() error {
return c.underlay.Close()
}
func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
cfg := config.FromContext(ctx, Name).(*Config)
if !strings.HasPrefix(cfg.Websocket.Path, "/") {
return nil, common.NewError("websocket path must start with \"/\"")
}
if cfg.Websocket.Host == "" {
cfg.Websocket.Host = cfg.RemoteHost
log.Warn("empty websocket hostname")
}
log.Debug("websocket client created")
return &Client{
hostname: cfg.Websocket.Host,
path: cfg.Websocket.Path,
underlay: underlay,
}, nil
}