-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathapi.go
110 lines (92 loc) · 2.26 KB
/
api.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
package libcore
import (
"errors"
"net"
"strings"
"sync"
"github.com/sagernet/sagerconnect/api"
"github.com/sirupsen/logrus"
"libcore/comm"
)
type ApiInstance struct {
access sync.Mutex
deviceName string
socksPort int32
dnsPort int32
debug bool
bypassLan bool
conn *net.UDPConn
started bool
}
func NewApiInstance(deviceName string, socksPort int32, dnsPort int32, debug bool, bypassLan bool) *ApiInstance {
return &ApiInstance{
deviceName: deviceName,
socksPort: socksPort,
dnsPort: dnsPort,
debug: debug,
bypassLan: bypassLan,
}
}
func (i *ApiInstance) Start() (err error) {
i.access.Lock()
defer i.access.Unlock()
if i.started {
return errors.New("already started")
}
i.conn, err = net.ListenUDP("udp4", &net.UDPAddr{
IP: net.IPv4zero,
Port: 11451,
})
if err != nil {
return err
}
i.started = true
go i.loop()
return nil
}
func (i *ApiInstance) Close() {
i.access.Lock()
defer i.access.Unlock()
if i.started {
i.started = false
comm.CloseIgnore(i.conn)
}
}
func (i *ApiInstance) loop() {
buffer := make([]byte, 2048)
for i.started {
length, addr, err := i.conn.ReadFrom(buffer)
if err != nil {
continue
}
query, err := api.ParseQuery(buffer[:length])
if err != nil {
if err != nil && strings.Contains(err.Error(), "upgrade") {
message, err := api.MakeResponse(&api.Response{Version: api.Version, DeviceName: "", SocksPort: 0, DnsPort: 0, Debug: false, BypassLan: false})
if err != nil {
logrus.Warnf("api: make response error: %v", err)
continue
}
_, err = i.conn.WriteTo(message, addr)
if err != nil {
logrus.Warnf("api: send response error: %v", err)
continue
}
}
logrus.Warnf("api: parse error: %v", err)
continue
}
logrus.Infof("api: new query from %s (%s)", query.DeviceName, addr.String())
response := api.Response{Version: api.Version, DeviceName: i.deviceName, SocksPort: uint16(i.socksPort), DnsPort: uint16(i.dnsPort), Debug: i.debug, BypassLan: i.bypassLan}
message, err := api.MakeResponse(&response)
if err != nil {
logrus.Warnf("api: make response error: %v", err)
continue
}
_, err = i.conn.WriteTo(message, addr)
if err != nil {
logrus.Warnf("api: send response error: %v", err)
continue
}
}
}