-
Notifications
You must be signed in to change notification settings - Fork 9
/
handler.go
118 lines (98 loc) · 2.31 KB
/
handler.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
package main
import (
"context"
"io"
"net"
"github.com/maskedeken/gost-plugin/gost/proxy"
"github.com/maskedeken/gost-plugin/registry"
"github.com/maskedeken/gost-plugin/args"
C "github.com/maskedeken/gost-plugin/constant"
"github.com/maskedeken/gost-plugin/gost"
"github.com/maskedeken/gost-plugin/log"
)
type handler struct {
listener gost.Listener
transporter gost.Transporter
}
func (h *handler) Close() (err error) {
return h.listener.Close()
}
func (h *handler) Serve(ctx context.Context) {
go func() {
for {
conn, err := h.listener.AcceptConn()
if err != nil {
log.Errorf("failed to accept connection: %s", err)
select {
case <-ctx.Done():
return
default:
continue
}
}
go func(inbound net.Conn) {
defer inbound.Close()
outbound, err := h.transporter.DialConn()
if err != nil {
log.Errorf("failed to dial connection: %s", err)
return
}
defer outbound.Close()
errChan := make(chan error, 2)
copy := func(a, b net.Conn) {
_, err := io.Copy(a, b)
errChan <- err
return
}
go copy(inbound, outbound)
go copy(outbound, inbound)
err = <-errChan
if err != nil {
log.Debugf("connection ends with error: %s", err)
}
}(conn)
}
}()
go h.listener.Serve(ctx)
}
func newHandler(ctx context.Context) (*handler, error) {
var listener gost.Listener
var transporter gost.Transporter
var err error
options := ctx.Value(C.OPTIONS).(*args.Options)
if options.Server { // server mode
log.Warnln("running in server mode")
var newListener registry.ListenerCreator
newListener, err = registry.GetListenerCreator(options.Mode)
if err != nil {
return nil, err
}
listener, err = newListener(ctx)
if err != nil {
return nil, err
}
transporter, err = proxy.NewTCPTransporter(ctx)
if err != nil {
return nil, err
}
} else { // client mode
log.Warnln("running in client mode")
var newTransporter registry.TransporterCreator
newTransporter, err = registry.GetTransporterCreator(options.Mode)
if err != nil {
return nil, err
}
transporter, err = newTransporter(ctx)
if err != nil {
return nil, err
}
listener, err = proxy.NewTCPListener(ctx)
if err != nil {
return nil, err
}
}
return &handler{
listener: listener,
transporter: transporter,
}, nil
}