You've already forked v2ray-core
Compare commits
261 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc81b0aae2 | ||
|
|
b49f76cd1c | ||
|
|
9471b5b066 | ||
|
|
5dc05d6352 | ||
|
|
e30f466424 | ||
|
|
2e0d54fd4c | ||
|
|
d343cb1ee6 | ||
|
|
7a09fcdc2f | ||
|
|
b0d009664a | ||
|
|
3d2431d21c | ||
|
|
d04e145442 | ||
|
|
d75cb28413 | ||
|
|
9f68062d48 | ||
|
|
d70b997d84 | ||
|
|
dc0cbce6e1 | ||
|
|
edc5bbbb72 | ||
|
|
66e8090d3a | ||
|
|
805bbe5fe4 | ||
|
|
31be091a55 | ||
|
|
f108633e2e | ||
|
|
d2263a452d | ||
|
|
dfc03ff939 | ||
|
|
13dde1799d | ||
|
|
c84629c374 | ||
|
|
817cc8d82e | ||
|
|
13ab2622c5 | ||
|
|
0727aa0da9 | ||
|
|
3a15f799c2 | ||
|
|
bae0de7d95 | ||
|
|
80312627c4 | ||
|
|
3d167a6855 | ||
|
|
010f34c76c | ||
|
|
0747203132 | ||
|
|
1600a59254 | ||
|
|
c5a92e00ef | ||
|
|
68b85cce60 | ||
|
|
9d2407f4e4 | ||
|
|
cdb0debcb0 | ||
|
|
5f3f173b5e | ||
|
|
35aa16d40d | ||
|
|
de4836c720 | ||
|
|
63d3c9fa30 | ||
|
|
687e008c9a | ||
|
|
43dacc3936 | ||
|
|
aabb9137e1 | ||
|
|
33d2513e3c | ||
|
|
5b58066345 | ||
|
|
d3f323e24b | ||
|
|
187688cacb | ||
|
|
72339a3509 | ||
|
|
ac3b91a877 | ||
|
|
5e1c6fe816 | ||
|
|
a54c39b4ac | ||
|
|
c221802963 | ||
|
|
be4f3d0772 | ||
|
|
fbb44e7e02 | ||
|
|
369256c82f | ||
|
|
531be77a59 | ||
|
|
97dc7b30de | ||
|
|
360c222c1c | ||
|
|
1fb9a911cd | ||
|
|
6006fd9ca7 | ||
|
|
59fa064cae | ||
|
|
3373e62193 | ||
|
|
2c2c569c77 | ||
|
|
687ae6c50e | ||
|
|
35ba8710e0 | ||
|
|
a7ef82ffbc | ||
|
|
ca980f5718 | ||
|
|
aae99a8e98 | ||
|
|
f37b04a690 | ||
|
|
e13c97d162 | ||
|
|
2af4b16913 | ||
|
|
2320bc3304 | ||
|
|
751a105324 | ||
|
|
b3bbd80674 | ||
|
|
4e80ed05d9 | ||
|
|
426a58707f | ||
|
|
9b4d9cf0e7 | ||
|
|
f049b3cc2b | ||
|
|
b81d091fb8 | ||
|
|
9bd8822668 | ||
|
|
ad59e56925 | ||
|
|
4a67587873 | ||
|
|
8b936bc816 | ||
|
|
9ae4611eac | ||
|
|
14996da74a | ||
|
|
7a14f646ee | ||
|
|
67d597af95 | ||
|
|
5a311cbe08 | ||
|
|
e866ff24a4 | ||
|
|
e33b7df34c | ||
|
|
5d9e6b0799 | ||
|
|
39939b00f0 | ||
|
|
be4cfdf61c | ||
|
|
be026870f7 | ||
|
|
348893a02a | ||
|
|
35a0ed6fb4 | ||
|
|
84f660bbbc | ||
|
|
8ad04f911d | ||
|
|
0a32345af9 | ||
|
|
f87d7f36f5 | ||
|
|
f488a63d97 | ||
|
|
b060bb3b94 | ||
|
|
d26ee5441e | ||
|
|
fc6a706166 | ||
|
|
c1f91567ad | ||
|
|
22ef12a456 | ||
|
|
63f3108737 | ||
|
|
ab3173039b | ||
|
|
b5910dccae | ||
|
|
f8ad1f4a3e | ||
|
|
da9f1a8013 | ||
|
|
f3a83c57ab | ||
|
|
78f87c4f60 | ||
|
|
e023859ef0 | ||
|
|
5f920a9e94 | ||
|
|
bd9b7c586e | ||
|
|
67793eb3e0 | ||
|
|
fd50e8e12b | ||
|
|
1ee76d31fa | ||
|
|
1d13f47f9c | ||
|
|
5ec948f690 | ||
|
|
af6abfa3e3 | ||
|
|
91f2a40dae | ||
|
|
922e761bef | ||
|
|
c5f09c64a2 | ||
|
|
c6a7389817 | ||
|
|
ce5bc72f0c | ||
|
|
5e9017720e | ||
|
|
24e575f2cd | ||
|
|
60f4292882 | ||
|
|
88ae8248a5 | ||
|
|
dc6b7e2e75 | ||
|
|
6317768cab | ||
|
|
b28d718b79 | ||
|
|
1a3f51ade7 | ||
|
|
8f6a972970 | ||
|
|
d38e62932d | ||
|
|
7de7588ec2 | ||
|
|
c518726910 | ||
|
|
fbdb1e09d7 | ||
|
|
9ade07db03 | ||
|
|
5291624165 | ||
|
|
5f5d28009f | ||
|
|
28432cfd4c | ||
|
|
9ad96949b0 | ||
|
|
8b37edd02d | ||
|
|
d08cba000f | ||
|
|
3423adaea4 | ||
|
|
7a31e7a0c2 | ||
|
|
7f2ba0d106 | ||
|
|
948f04921d | ||
|
|
ea2c491ade | ||
|
|
11e310298c | ||
|
|
0f74c618de | ||
|
|
9b72d3cbd7 | ||
|
|
bd4ca7b37f | ||
|
|
cdb4c56546 | ||
|
|
64e38ba851 | ||
|
|
bbca180dba | ||
|
|
04d956462c | ||
|
|
3fd66ad795 | ||
|
|
e49fb2f50d | ||
|
|
59125f665b | ||
|
|
fcad4aa212 | ||
|
|
0da987ec43 | ||
|
|
2ae8e5d033 | ||
|
|
2839ce7a88 | ||
|
|
5d20e3f70b | ||
|
|
e6e0419958 | ||
|
|
a9da266bf9 | ||
|
|
98025e1457 | ||
|
|
85c5171d8d | ||
|
|
e7bf0c2e49 | ||
|
|
8eab746c96 | ||
|
|
fdeb8b4f89 | ||
|
|
07a86f549b | ||
|
|
6a878432dc | ||
|
|
d08ffedf48 | ||
|
|
0a34ec0be6 | ||
|
|
7a1bdfcf00 | ||
|
|
2268f3d1bc | ||
|
|
d83a0ce5d2 | ||
|
|
55e5268ce8 | ||
|
|
ad1353ac2f | ||
|
|
786775ea80 | ||
|
|
39737f6fc1 | ||
|
|
933e244d92 | ||
|
|
89a876a6d4 | ||
|
|
d9884b4010 | ||
|
|
8ecec9b49d | ||
|
|
bb3ceb3d7b | ||
|
|
49056d9942 | ||
|
|
8951c4da71 | ||
|
|
99a63f1633 | ||
|
|
99821dc2fb | ||
|
|
125ef8372c | ||
|
|
41d89e6d1e | ||
|
|
9876844296 | ||
|
|
a83009afc4 | ||
|
|
7bc94d55c6 | ||
|
|
6417adb56d | ||
|
|
d025b8d48f | ||
|
|
0bca6e8657 | ||
|
|
a5a70afdb8 | ||
|
|
338dc1ebb6 | ||
|
|
c7871a3ab2 | ||
|
|
2a778762b1 | ||
|
|
667b71aad0 | ||
|
|
210a32dc12 | ||
|
|
22519353c3 | ||
|
|
32e8deb6e8 | ||
|
|
45d801b922 | ||
|
|
6c8b4f5db3 | ||
|
|
d7440bb1d6 | ||
|
|
856f2a2dd3 | ||
|
|
4b9e506dba | ||
|
|
f7ce9d3be6 | ||
|
|
956b47f6ae | ||
|
|
02e3c17c97 | ||
|
|
40ec84e222 | ||
|
|
2209294dfc | ||
|
|
0a49628555 | ||
|
|
e382eaa59f | ||
|
|
4c093a2107 | ||
|
|
a5ae6a0f4e | ||
|
|
bfb4e0d9b0 | ||
|
|
273c8f6c57 | ||
|
|
062d05fdcf | ||
|
|
66bb7879e0 | ||
|
|
c8cd1320c7 | ||
|
|
a36582b294 | ||
|
|
863237b518 | ||
|
|
4853a1a6d3 | ||
|
|
de28198234 | ||
|
|
7b3cf631c2 | ||
|
|
ee22082fb4 | ||
|
|
00aeb29e46 | ||
|
|
2bf9edfe7d | ||
|
|
d250013c99 | ||
|
|
d06c75f926 | ||
|
|
7259b3363b | ||
|
|
fed2933043 | ||
|
|
5e576e11bb | ||
|
|
49441a5050 | ||
|
|
a0fda39274 | ||
|
|
3e9e9b520e | ||
|
|
1fe090dbfd | ||
|
|
427bed5ddb | ||
|
|
16b529093d | ||
|
|
fecf9cc5b8 | ||
|
|
7ef66c57dc | ||
|
|
29f69d63c4 | ||
|
|
20f16309e6 | ||
|
|
0d60d2449a | ||
|
|
2eced2bd6c | ||
|
|
8c4a6d94f9 | ||
|
|
8c96b1961b | ||
|
|
508f79f95f | ||
|
|
cb1356be75 |
45
.travis.yml
45
.travis.yml
@@ -1,37 +1,34 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6.3
|
||||
|
||||
- 1.7.3
|
||||
go_import_path: v2ray.com/core
|
||||
git:
|
||||
depth: 5
|
||||
|
||||
script:
|
||||
- go test -tags json github.com/v2ray/v2ray-core/...
|
||||
|
||||
- go test -tags json v2ray.com/core/...
|
||||
after_success:
|
||||
- ./testing/coverage/coverall
|
||||
|
||||
- ./testing/coverage/coverall
|
||||
before_deploy:
|
||||
- rvm 1.9.3 do gem install mime-types -v 2.6.2
|
||||
- "./tools/release/release-ci.sh"
|
||||
|
||||
- ./tools/release/release-ci.sh
|
||||
- gem install octokit -v 4.3.0
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: "Nbno1ibFpq0DC6y0mkN6NFTbDQinRAEQo2Jl5lvsbiaX9m4CK59xG8XOcmZ3mqqdeioj6m9X5BVe2UtCZjmXmnyPq0FYNFHAPTfd2VrcOpi0fWLD9ndTYAsqjxrqPGK62XVjPbG8U2pGdq2yCOb0qQ9DlahDhVIMzQ/GYuRDps25fPGftepdPwlrwOfYCIvAHoi3GEozuS67WNEx/YtmZTce/2Qebdmwf44hUNaQibeXEspu9wQcp9M/i7aTuX/tUbn7rVCQ4TfoIJU1C1qKedUw0QYMjqP08Wn6UjwwhbblsJKFv8Kc0nx+i2K9CvvLyaBBIVY2Ggxj4Niy+X4VbyWWzdKx+0FXlmKh3U/hJdMZU3OrnwliBns2X3tCHSq7/+7ynLs3UZ4wCkCl7rQYucJ2mlvGquohQV6MX2vjl73y+pYljf+PKYbSDBb7iUOjllisRD+HmDmGQl81BvdEpN/K/BlfsTwHoHxsALSTjRljSngH51SUvjnaVbi/JolJ3lomTr1vCHl4WUiQVLnh7O2Cg7QLNMNieoblnh9yDQG9wC4xuzOJ/AaxRd/pRZMeIooQ1zsHOe+47C1YAep88b+9xtRqVMozAjk/XgNzWjuT2R8G7lZDq0mL9VajD/NUjM3Yrswoft9A3DRmR+lIFJR+fJb8tNf+k1OczE4lesg="
|
||||
api_key:
|
||||
secure: h7P6y7jHe0yALKgXb9HyPAlE6JPOB/BiScMlqsG6MUF0G29JrEjcDXh/jZm8HB82OfUG3zPBtr5m0P3LUoM60EQQ96/yE9KKrhEBeyF+E9CAOUHx7Ar4XDR7dG7/Wv+q3ZRFl+4CB5f7xbt9qlobqXkeffngeu9RNWngqVvbyTWIZclx7NYl5haf/hhqGcX2OPKQQfjvOsnP+uLmqiRJBbaYQMzPmvjaQJ9cB6Z11ctJqunk3bN89nV86uaHLqmz8nfk3/J7RjdeT0mqgRYVwfMavZifGPISlgsZd7N0PqiiWB7gZqzjbiSCur+PtnVScYfTlfNoRP+XJtVx3OFnepffSvyE6zOP20MEINAMOgME68Zzkaab8JnDVwj0eTsPNEDpK+E+RUZ1IkaAvVZ19L0qNYwO6bP8koUI4cFDI45srcx0o5xC7Hzz1eaSm5ZJZ3iwwzFZE2vFm83pcQilopG0E7gTYyB+fk0x6sca5MY1PhHAByvBbvYhsCBV4x4o0N1lD1V3QXhvljJL4qieFybwg8g0hdUNeSrm2+NxPqKpEHUQWQFGsl0OGMy2Ji6u/NG5tSvfWKUUsXpkueyutvfTb9D94Xk4s1eNGMG+BHFIGHRTZzX6XXB7/j3zObWApD3h8SIbXjfL0mLaKaBeMyLwf2tlsKTgzwEjvIzcNfQ=
|
||||
file:
|
||||
- "$GOPATH/bin/v2ray-macos.zip"
|
||||
- "$GOPATH/bin/v2ray-windows-64.zip"
|
||||
- "$GOPATH/bin/v2ray-windows-32.zip"
|
||||
- "$GOPATH/bin/v2ray-linux-64.zip"
|
||||
- "$GOPATH/bin/v2ray-linux-32.zip"
|
||||
- "$GOPATH/bin/v2ray-linux-arm.zip"
|
||||
- "$GOPATH/bin/v2ray-linux-arm64.zip"
|
||||
- "$GOPATH/bin/v2ray-linux-mips64.zip"
|
||||
- "$GOPATH/bin/v2ray-freebsd-64.zip"
|
||||
- "$GOPATH/bin/v2ray-freebsd-32.zip"
|
||||
- "$GOPATH/bin/metadata.txt"
|
||||
- $GOPATH/bin/v2ray-macos.zip
|
||||
- $GOPATH/bin/v2ray-windows-64.zip
|
||||
- $GOPATH/bin/v2ray-windows-32.zip
|
||||
- $GOPATH/bin/v2ray-linux-64.zip
|
||||
- $GOPATH/bin/v2ray-linux-32.zip
|
||||
- $GOPATH/bin/v2ray-linux-arm.zip
|
||||
- $GOPATH/bin/v2ray-linux-arm64.zip
|
||||
- $GOPATH/bin/v2ray-linux-mips64.zip
|
||||
- $GOPATH/bin/v2ray-freebsd-64.zip
|
||||
- $GOPATH/bin/v2ray-freebsd-32.zip
|
||||
- $GOPATH/bin/v2ray-openbsd-64.zip
|
||||
- $GOPATH/bin/v2ray-openbsd-32.zip
|
||||
- $GOPATH/bin/metadata.txt
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
|
||||
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
@@ -2,5 +2,12 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
|
||||
"go.buildTags": "json"
|
||||
"go.buildTags": "json",
|
||||
|
||||
"protoc": {
|
||||
"options": [
|
||||
"--proto_path=$GOPATH/src/",
|
||||
"--proto_path=$GOPATH/src/github.com/google/protobuf/src"
|
||||
]
|
||||
}
|
||||
}
|
||||
4
.vscode/tasks.json
vendored
4
.vscode/tasks.json
vendored
@@ -6,7 +6,7 @@
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "build",
|
||||
"args": ["-tags", "json", "github.com/v2ray/v2ray-core/..."],
|
||||
"args": ["-tags", "json", "v2ray.com/core/..."],
|
||||
"isBuildCommand": true,
|
||||
"problemMatcher": {
|
||||
"owner": "go",
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
{
|
||||
"taskName": "test",
|
||||
"args": ["-tags", "json", "github.com/v2ray/v2ray-core/..."],
|
||||
"args": ["-tags", "json", "v2ray.com/core/..."],
|
||||
"isBuildCommand": false
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
[2]: https://travis-ci.org/v2ray/v2ray-core "Travis-CI Build Status"
|
||||
[3]: https://codecov.io/github/v2ray/v2ray-core/coverage.svg?branch=master "Coverage badge"
|
||||
[4]: https://codecov.io/github/v2ray/v2ray-core?branch=master "Codecov Status"
|
||||
[5]: https://goreportcard.com/badge/github.com/v2ray/v2ray-core "Go Report badge"
|
||||
[6]: https://goreportcard.com/report/github.com/v2ray/v2ray-core "Go Report"
|
||||
[7]: https://godoc.org/github.com/v2ray/v2ray-core?status.svg "GoDoc badge"
|
||||
[8]: https://godoc.org/github.com/v2ray/v2ray-core "GoDoc"
|
||||
[5]: https://goreportcard.com/badge/v2ray.com/core "Go Report badge"
|
||||
[6]: https://goreportcard.com/report/v2ray.com/core "Go Report"
|
||||
[7]: https://godoc.org/v2ray.com/core?status.svg "GoDoc badge"
|
||||
[8]: https://godoc.org/v2ray.com/core "GoDoc"
|
||||
[9]: https://codebeat.co/badges/f2354ca8-3e24-463d-a2e3-159af73b2477 "Codebeat badge"
|
||||
[10]: https://codebeat.co/projects/github-com-v2ray-v2ray-core "Codebeat"
|
||||
|
||||
|
||||
28
all.go
Normal file
28
all.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
// The following are necessary as they register handlers in their init functions.
|
||||
_ "v2ray.com/core/app/dns"
|
||||
_ "v2ray.com/core/app/proxy"
|
||||
_ "v2ray.com/core/app/router"
|
||||
|
||||
_ "v2ray.com/core/proxy/blackhole"
|
||||
_ "v2ray.com/core/proxy/dokodemo"
|
||||
_ "v2ray.com/core/proxy/freedom"
|
||||
_ "v2ray.com/core/proxy/http"
|
||||
_ "v2ray.com/core/proxy/shadowsocks"
|
||||
_ "v2ray.com/core/proxy/socks"
|
||||
_ "v2ray.com/core/proxy/vmess/inbound"
|
||||
_ "v2ray.com/core/proxy/vmess/outbound"
|
||||
|
||||
_ "v2ray.com/core/transport/internet/kcp"
|
||||
_ "v2ray.com/core/transport/internet/tcp"
|
||||
_ "v2ray.com/core/transport/internet/tls"
|
||||
_ "v2ray.com/core/transport/internet/udp"
|
||||
_ "v2ray.com/core/transport/internet/ws"
|
||||
|
||||
_ "v2ray.com/core/transport/internet/authenticators/http"
|
||||
_ "v2ray.com/core/transport/internet/authenticators/noop"
|
||||
_ "v2ray.com/core/transport/internet/authenticators/srtp"
|
||||
_ "v2ray.com/core/transport/internet/authenticators/utp"
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"v2ray.com/core/app"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package dispatcher
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"github.com/v2ray/v2ray-core/transport/ray"
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/transport/ray"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -12,5 +12,5 @@ const (
|
||||
|
||||
// PacketDispatcher dispatch a packet and possibly further network payload to its destination.
|
||||
type PacketDispatcher interface {
|
||||
DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay
|
||||
DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package impl
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/app/proxyman"
|
||||
"github.com/v2ray/v2ray-core/app/router"
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"github.com/v2ray/v2ray-core/transport/ray"
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/app/proxyman"
|
||||
"v2ray.com/core/app/router"
|
||||
"v2ray.com/core/common/alloc"
|
||||
"v2ray.com/core/common/log"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/transport/ray"
|
||||
)
|
||||
|
||||
type DefaultDispatcher struct {
|
||||
ohm proxyman.OutboundHandlerManager
|
||||
router router.Router
|
||||
router *router.Router
|
||||
}
|
||||
|
||||
func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
|
||||
@@ -24,7 +24,7 @@ func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
|
||||
return d
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Used by app.Space only.
|
||||
func (this *DefaultDispatcher) Initialize(space app.Space) error {
|
||||
if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) {
|
||||
log.Error("DefaultDispatcher: OutboundHandlerManager is not found in the space.")
|
||||
@@ -33,7 +33,7 @@ func (this *DefaultDispatcher) Initialize(space app.Space) error {
|
||||
this.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
|
||||
|
||||
if space.HasApp(router.APP_ID) {
|
||||
this.router = space.GetApp(router.APP_ID).(router.Router)
|
||||
this.router = space.GetApp(router.APP_ID).(*router.Router)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -43,13 +43,13 @@ func (this *DefaultDispatcher) Release() {
|
||||
|
||||
}
|
||||
|
||||
func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay {
|
||||
func (this *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
|
||||
direct := ray.NewRay()
|
||||
dispatcher := this.ohm.GetDefaultHandler()
|
||||
destination := session.Destination
|
||||
|
||||
if this.router != nil {
|
||||
if tag, err := this.router.TakeDetour(destination); err == nil {
|
||||
if tag, err := this.router.TakeDetour(session); err == nil {
|
||||
if handler := this.ohm.GetHandler(tag); handler != nil {
|
||||
log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].")
|
||||
dispatcher = handler
|
||||
@@ -61,7 +61,7 @@ func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta
|
||||
}
|
||||
}
|
||||
|
||||
if meta.AllowPassiveConnection {
|
||||
if session.Inbound != nil && session.Inbound.AllowPassiveConnection {
|
||||
go dispatcher.Dispatch(destination, alloc.NewLocalBuffer(32).Clear(), direct)
|
||||
} else {
|
||||
go this.FilterPacketAndDispatch(destination, direct, dispatcher)
|
||||
@@ -70,7 +70,7 @@ func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta
|
||||
return direct
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Visible for testing.
|
||||
func (this *DefaultDispatcher) FilterPacketAndDispatch(destination v2net.Destination, link ray.OutboundRay, dispatcher proxy.OutboundHandler) {
|
||||
payload, err := link.OutboundInput().Read()
|
||||
if err != nil {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"github.com/v2ray/v2ray-core/transport/ray"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/transport/ray"
|
||||
)
|
||||
|
||||
type TestPacketDispatcher struct {
|
||||
@@ -30,7 +30,7 @@ func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic
|
||||
}
|
||||
}
|
||||
|
||||
func (this *TestPacketDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay {
|
||||
func (this *TestPacketDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
|
||||
traffic := ray.NewRay()
|
||||
this.Destination <- session.Destination
|
||||
go this.Handler(session.Destination, traffic)
|
||||
|
||||
@@ -3,10 +3,18 @@ package dns
|
||||
import (
|
||||
"net"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"v2ray.com/core/common/log"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Hosts map[string]net.IP
|
||||
NameServers []v2net.Destination
|
||||
func (this *Config) GetInternalHosts() map[string]net.IP {
|
||||
hosts := make(map[string]net.IP)
|
||||
for domain, ipOrDomain := range this.GetHosts() {
|
||||
address := ipOrDomain.AsAddress()
|
||||
if address.Family().IsDomain() {
|
||||
log.Warning("DNS: Ignoring domain address in static hosts: ", address.Domain())
|
||||
continue
|
||||
}
|
||||
hosts[domain] = address.IP()
|
||||
}
|
||||
return hosts
|
||||
}
|
||||
|
||||
85
app/dns/config.pb.go
Normal file
85
app/dns/config.pb.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/app/dns/config.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package dns is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
v2ray.com/core/app/dns/config.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Config
|
||||
*/
|
||||
package dns
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v2ray_core_common_net "v2ray.com/core/common/net"
|
||||
import v2ray_core_common_net2 "v2ray.com/core/common/net"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Config struct {
|
||||
// Nameservers used by this DNS. Only traditional UDP servers are support at the moment.
|
||||
// A special value 'localhost' as a domain address can be set to use DNS on local system.
|
||||
NameServers []*v2ray_core_common_net2.Endpoint `protobuf:"bytes,1,rep,name=NameServers" json:"NameServers,omitempty"`
|
||||
// Static hosts. Domain to IP.
|
||||
Hosts map[string]*v2ray_core_common_net.IPOrDomain `protobuf:"bytes,2,rep,name=Hosts" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *Config) Reset() { *m = Config{} }
|
||||
func (m *Config) String() string { return proto.CompactTextString(m) }
|
||||
func (*Config) ProtoMessage() {}
|
||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Config) GetNameServers() []*v2ray_core_common_net2.Endpoint {
|
||||
if m != nil {
|
||||
return m.NameServers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Config) GetHosts() map[string]*v2ray_core_common_net.IPOrDomain {
|
||||
if m != nil {
|
||||
return m.Hosts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Config)(nil), "v2ray.core.app.dns.Config")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/app/dns/config.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 272 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x90, 0x31, 0x4b, 0xc4, 0x30,
|
||||
0x14, 0x80, 0x49, 0xcb, 0x1d, 0x98, 0x2e, 0x92, 0x41, 0x4a, 0x17, 0xab, 0x22, 0x16, 0x85, 0x04,
|
||||
0xea, 0xa0, 0xe8, 0xe4, 0xe9, 0x81, 0x2e, 0x7a, 0xd4, 0x4d, 0xa7, 0xd8, 0x44, 0x29, 0x9a, 0xf7,
|
||||
0x42, 0x12, 0x0b, 0xfd, 0xc1, 0xfe, 0x0f, 0xb9, 0x06, 0xf1, 0xd0, 0xbb, 0x2d, 0x84, 0xef, 0xcb,
|
||||
0xfb, 0xf2, 0xe8, 0x41, 0x5f, 0x3b, 0x39, 0xf0, 0x16, 0x8d, 0x68, 0xd1, 0x69, 0x21, 0xad, 0x15,
|
||||
0x0a, 0xbc, 0x68, 0x11, 0x5e, 0xbb, 0x37, 0x6e, 0x1d, 0x06, 0x64, 0xec, 0x07, 0x72, 0x9a, 0x4b,
|
||||
0x6b, 0xb9, 0x02, 0x5f, 0x1c, 0xfd, 0x11, 0x5b, 0x34, 0x06, 0x41, 0x80, 0x0e, 0x42, 0x2a, 0xe5,
|
||||
0xb4, 0xf7, 0x51, 0x2e, 0x4e, 0x36, 0x83, 0x4a, 0xfb, 0xd0, 0x81, 0x0c, 0x1d, 0x42, 0x84, 0xf7,
|
||||
0xbf, 0x08, 0x9d, 0x5e, 0x8f, 0xa3, 0xd9, 0x15, 0xcd, 0xee, 0xa5, 0xd1, 0x8f, 0xda, 0xf5, 0xda,
|
||||
0xf9, 0x9c, 0x94, 0x69, 0x95, 0xd5, 0xbb, 0x7c, 0x25, 0x25, 0xbe, 0xc4, 0x41, 0x07, 0x3e, 0x07,
|
||||
0x65, 0xb1, 0x83, 0xd0, 0xac, 0x3a, 0xec, 0x92, 0x4e, 0x6e, 0xd1, 0x07, 0x9f, 0x27, 0xa3, 0x7c,
|
||||
0xc8, 0xff, 0xff, 0x83, 0xc7, 0x69, 0x7c, 0xe4, 0xe6, 0x10, 0xdc, 0xd0, 0x44, 0xa7, 0x78, 0xa6,
|
||||
0xf4, 0xf7, 0x92, 0x6d, 0xd3, 0xf4, 0x5d, 0x0f, 0x39, 0x29, 0x49, 0xb5, 0xd5, 0x2c, 0x8f, 0xec,
|
||||
0x8c, 0x4e, 0x7a, 0xf9, 0xf1, 0xa9, 0xf3, 0xa4, 0x24, 0x55, 0x56, 0xef, 0x6d, 0x28, 0xbb, 0x5b,
|
||||
0x3c, 0xb8, 0x1b, 0x34, 0xb2, 0x83, 0x26, 0xf2, 0x17, 0xc9, 0x39, 0x99, 0x1d, 0xd3, 0x9d, 0x16,
|
||||
0xcd, 0x9a, 0x9e, 0x59, 0x16, 0x83, 0x16, 0xcb, 0x75, 0x3c, 0xa5, 0x0a, 0xfc, 0xcb, 0x74, 0x5c,
|
||||
0xcd, 0xe9, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x43, 0x85, 0xa5, 0x73, 0xab, 0x01, 0x00, 0x00,
|
||||
}
|
||||
18
app/dns/config.proto
Normal file
18
app/dns/config.proto
Normal file
@@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.app.dns;
|
||||
option go_package = "dns";
|
||||
option java_package = "com.v2ray.core.app.dns";
|
||||
option java_outer_classname = "ConfigProto";
|
||||
|
||||
import "v2ray.com/core/common/net/address.proto";
|
||||
import "v2ray.com/core/common/net/destination.proto";
|
||||
|
||||
message Config {
|
||||
// Nameservers used by this DNS. Only traditional UDP servers are support at the moment.
|
||||
// A special value 'localhost' as a domain address can be set to use DNS on local system.
|
||||
repeated v2ray.core.common.net.Endpoint NameServers = 1;
|
||||
|
||||
// Static hosts. Domain to IP.
|
||||
map<string, v2ray.core.common.net.IPOrDomain> Hosts = 2;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
)
|
||||
|
||||
func (this *Config) UnmarshalJSON(data []byte) error {
|
||||
type JsonConfig struct {
|
||||
Servers []v2net.AddressJson `json:"servers"`
|
||||
Hosts map[string]v2net.AddressJson `json:"hosts"`
|
||||
}
|
||||
jsonConfig := new(JsonConfig)
|
||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
this.NameServers = make([]v2net.Destination, len(jsonConfig.Servers))
|
||||
for idx, server := range jsonConfig.Servers {
|
||||
this.NameServers[idx] = v2net.UDPDestination(server.Address, v2net.Port(53))
|
||||
}
|
||||
|
||||
if jsonConfig.Hosts != nil {
|
||||
this.Hosts = make(map[string]net.IP)
|
||||
for domain, ip := range jsonConfig.Hosts {
|
||||
if ip.Address.Family().IsDomain() {
|
||||
return errors.New(ip.Address.String() + " is not an IP.")
|
||||
}
|
||||
this.Hosts[domain] = ip.Address.IP()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package dns_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/app/dns"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestConfigParsing(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rawJson := `{
|
||||
"servers": ["8.8.8.8"]
|
||||
}`
|
||||
|
||||
config := new(Config)
|
||||
err := json.Unmarshal([]byte(rawJson), config)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Int(len(config.NameServers)).Equals(1)
|
||||
assert.Destination(config.NameServers[0]).IsUDP()
|
||||
assert.Address(config.NameServers[0].Address()).Equals(v2net.IPAddress([]byte{8, 8, 8, 8}))
|
||||
assert.Port(config.NameServers[0].Port()).Equals(v2net.Port(53))
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package dns
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"v2ray.com/core/app"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -5,13 +5,13 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app/dispatcher"
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"github.com/v2ray/v2ray-core/common/dice"
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"github.com/v2ray/v2ray-core/transport/internet/udp"
|
||||
"v2ray.com/core/app/dispatcher"
|
||||
"v2ray.com/core/common/alloc"
|
||||
"v2ray.com/core/common/dice"
|
||||
"v2ray.com/core/common/log"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/transport/internet/udp"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
@@ -50,16 +50,14 @@ type UDPNameServer struct {
|
||||
|
||||
func NewUDPNameServer(address v2net.Destination, dispatcher dispatcher.PacketDispatcher) *UDPNameServer {
|
||||
s := &UDPNameServer{
|
||||
address: address,
|
||||
requests: make(map[uint16]*PendingRequest),
|
||||
udpServer: udp.NewUDPServer(&proxy.InboundHandlerMeta{
|
||||
AllowPassiveConnection: false,
|
||||
}, dispatcher),
|
||||
address: address,
|
||||
requests: make(map[uint16]*PendingRequest),
|
||||
udpServer: udp.NewUDPServer(dispatcher),
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Visible for testing.
|
||||
func (this *UDPNameServer) Cleanup() {
|
||||
expiredRequests := make([]uint16, 0, 16)
|
||||
now := time.Now()
|
||||
@@ -77,7 +75,7 @@ func (this *UDPNameServer) Cleanup() {
|
||||
expiredRequests = nil
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Visible for testing.
|
||||
func (this *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 {
|
||||
var id uint16
|
||||
this.Lock()
|
||||
@@ -102,7 +100,7 @@ func (this *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 {
|
||||
return id
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Visible for testing.
|
||||
func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc.Buffer) {
|
||||
msg := new(dns.Msg)
|
||||
err := msg.Unpack(payload.Value)
|
||||
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/app/dispatcher"
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/app/dispatcher"
|
||||
"v2ray.com/core/common/loader"
|
||||
"v2ray.com/core/common/log"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
@@ -32,7 +34,7 @@ func NewCacheServer(space app.Space, config *Config) *CacheServer {
|
||||
server := &CacheServer{
|
||||
records: make(map[string]*DomainRecord),
|
||||
servers: make([]NameServer, len(config.NameServers)),
|
||||
hosts: config.Hosts,
|
||||
hosts: config.GetInternalHosts(),
|
||||
}
|
||||
space.InitializeApplication(func() error {
|
||||
if !space.HasApp(dispatcher.APP_ID) {
|
||||
@@ -41,11 +43,18 @@ func NewCacheServer(space app.Space, config *Config) *CacheServer {
|
||||
}
|
||||
|
||||
dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
|
||||
for idx, ns := range config.NameServers {
|
||||
if ns.Address().Family().IsDomain() && ns.Address().Domain() == "localhost" {
|
||||
for idx, destPB := range config.NameServers {
|
||||
address := destPB.Address.AsAddress()
|
||||
if address.Family().IsDomain() && address.Domain() == "localhost" {
|
||||
server.servers[idx] = &LocalNameServer{}
|
||||
} else {
|
||||
server.servers[idx] = NewUDPNameServer(ns, dispatcher)
|
||||
dest := destPB.AsDestination()
|
||||
if dest.Network == v2net.Network_Unknown {
|
||||
dest.Network = v2net.Network_UDP
|
||||
}
|
||||
if dest.Network == v2net.Network_UDP {
|
||||
server.servers[idx] = NewUDPNameServer(dest, dispatcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(config.NameServers) == 0 {
|
||||
@@ -60,7 +69,7 @@ func (this *CacheServer) Release() {
|
||||
|
||||
}
|
||||
|
||||
//@Private
|
||||
// Private: Visible for testing.
|
||||
func (this *CacheServer) GetCached(domain string) []net.IP {
|
||||
this.RLock()
|
||||
defer this.RUnlock()
|
||||
@@ -103,3 +112,18 @@ func (this *CacheServer) Get(domain string) []net.IP {
|
||||
log.Debug("DNS: Returning nil for domain ", domain)
|
||||
return nil
|
||||
}
|
||||
|
||||
type CacheServerFactory struct{}
|
||||
|
||||
func (this CacheServerFactory) Create(space app.Space, config interface{}) (app.Application, error) {
|
||||
server := NewCacheServer(space, config.(*Config))
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func (this CacheServerFactory) AppId() app.ID {
|
||||
return APP_ID
|
||||
}
|
||||
|
||||
func init() {
|
||||
app.RegisterApplicationFactory(loader.GetType(new(Config)), CacheServerFactory{})
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package dns_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/app/dispatcher"
|
||||
dispatchers "github.com/v2ray/v2ray-core/app/dispatcher/impl"
|
||||
. "github.com/v2ray/v2ray-core/app/dns"
|
||||
"github.com/v2ray/v2ray-core/app/proxyman"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"github.com/v2ray/v2ray-core/proxy/freedom"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
"github.com/v2ray/v2ray-core/transport/internet"
|
||||
)
|
||||
|
||||
func TestDnsAdd(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
space := app.NewSpace()
|
||||
|
||||
outboundHandlerManager := proxyman.NewDefaultOutboundHandlerManager()
|
||||
outboundHandlerManager.SetDefaultHandler(
|
||||
freedom.NewFreedomConnection(
|
||||
&freedom.Config{},
|
||||
space,
|
||||
&proxy.OutboundHandlerMeta{
|
||||
Address: v2net.AnyIP,
|
||||
StreamSettings: &internet.StreamSettings{
|
||||
Type: internet.StreamConnectionTypeRawTCP,
|
||||
},
|
||||
}))
|
||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager)
|
||||
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
||||
|
||||
domain := "local.v2ray.com"
|
||||
server := NewCacheServer(space, &Config{
|
||||
NameServers: []v2net.Destination{
|
||||
v2net.UDPDestination(v2net.IPAddress([]byte{8, 8, 8, 8}), v2net.Port(53)),
|
||||
},
|
||||
})
|
||||
space.BindApp(APP_ID, server)
|
||||
space.Initialize()
|
||||
|
||||
ips := server.Get(domain)
|
||||
assert.Int(len(ips)).Equals(1)
|
||||
assert.IP(ips[0].To4()).Equals(net.IP([]byte{127, 0, 0, 1}))
|
||||
}
|
||||
133
app/proxy/proxy.go
Normal file
133
app/proxy/proxy.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/app/proxyman"
|
||||
"v2ray.com/core/common/alloc"
|
||||
v2io "v2ray.com/core/common/io"
|
||||
"v2ray.com/core/common/log"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/transport/internet"
|
||||
"v2ray.com/core/transport/ray"
|
||||
)
|
||||
|
||||
const (
|
||||
APP_ID = 7
|
||||
)
|
||||
|
||||
type OutboundProxy struct {
|
||||
outboundManager proxyman.OutboundHandlerManager
|
||||
}
|
||||
|
||||
func NewOutboundProxy(space app.Space) *OutboundProxy {
|
||||
proxy := new(OutboundProxy)
|
||||
space.InitializeApplication(func() error {
|
||||
if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) {
|
||||
return errors.New("Proxy: Outbound handler manager not found.")
|
||||
}
|
||||
proxy.outboundManager = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
|
||||
return nil
|
||||
})
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (this *OutboundProxy) RegisterDialer() {
|
||||
internet.ProxyDialer = this.Dial
|
||||
}
|
||||
|
||||
func (this *OutboundProxy) Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOptions) (internet.Connection, error) {
|
||||
handler := this.outboundManager.GetHandler(options.Proxy.Tag)
|
||||
if handler == nil {
|
||||
log.Warning("Proxy: Failed to get outbound handler with tag: ", options.Proxy.Tag)
|
||||
return internet.Dial(src, dest, internet.DialerOptions{
|
||||
Stream: options.Stream,
|
||||
})
|
||||
}
|
||||
stream := ray.NewRay()
|
||||
go handler.Dispatch(dest, alloc.NewLocalBuffer(32).Clear(), stream)
|
||||
return NewProxyConnection(src, dest, stream), nil
|
||||
}
|
||||
|
||||
func (this *OutboundProxy) Release() {
|
||||
|
||||
}
|
||||
|
||||
type ProxyConnection struct {
|
||||
stream ray.Ray
|
||||
closed bool
|
||||
localAddr net.Addr
|
||||
remoteAddr net.Addr
|
||||
|
||||
reader *v2io.ChanReader
|
||||
writer *v2io.ChainWriter
|
||||
}
|
||||
|
||||
func NewProxyConnection(src v2net.Address, dest v2net.Destination, stream ray.Ray) *ProxyConnection {
|
||||
return &ProxyConnection{
|
||||
stream: stream,
|
||||
localAddr: &net.TCPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: 0,
|
||||
},
|
||||
remoteAddr: &net.TCPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: 0,
|
||||
},
|
||||
reader: v2io.NewChanReader(stream.InboundOutput()),
|
||||
writer: v2io.NewChainWriter(stream.InboundInput()),
|
||||
}
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) Read(b []byte) (int, error) {
|
||||
if this.closed {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return this.reader.Read(b)
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) Write(b []byte) (int, error) {
|
||||
if this.closed {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return this.writer.Write(b)
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) Close() error {
|
||||
this.closed = true
|
||||
this.stream.InboundInput().Close()
|
||||
this.stream.InboundOutput().Release()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) LocalAddr() net.Addr {
|
||||
return this.localAddr
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) RemoteAddr() net.Addr {
|
||||
return this.remoteAddr
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) SetDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) SetReadDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) SetWriteDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) Reusable() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *ProxyConnection) SetReusable(bool) {
|
||||
|
||||
}
|
||||
68
app/proxy/proxy_test.go
Normal file
68
app/proxy/proxy_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package proxy_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"v2ray.com/core/app"
|
||||
. "v2ray.com/core/app/proxy"
|
||||
"v2ray.com/core/app/proxyman"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/proxy/freedom"
|
||||
"v2ray.com/core/testing/assert"
|
||||
"v2ray.com/core/testing/servers/tcp"
|
||||
"v2ray.com/core/transport/internet"
|
||||
)
|
||||
|
||||
func TestProxyDial(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
space := app.NewSpace()
|
||||
outboundManager := proxyman.NewDefaultOutboundHandlerManager()
|
||||
outboundManager.SetHandler("tag", freedom.NewFreedomConnection(&freedom.Config{}, space, &proxy.OutboundHandlerMeta{
|
||||
Tag: "tag",
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
Network: v2net.Network_RawTCP,
|
||||
},
|
||||
}))
|
||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundManager)
|
||||
|
||||
proxy := NewOutboundProxy(space)
|
||||
space.BindApp(APP_ID, proxy)
|
||||
|
||||
assert.Error(space.Initialize()).IsNil()
|
||||
|
||||
xor := func(b []byte) []byte {
|
||||
for idx, x := range b {
|
||||
b[idx] = x ^ 'c'
|
||||
}
|
||||
return b
|
||||
}
|
||||
tcpServer := &tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
conn, err := proxy.Dial(v2net.LocalHostIP, dest, internet.DialerOptions{
|
||||
Stream: &internet.StreamConfig{
|
||||
Network: v2net.Network_RawTCP,
|
||||
},
|
||||
Proxy: &internet.ProxyConfig{
|
||||
Tag: "tag",
|
||||
},
|
||||
})
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
_, err = conn.Write([]byte{'a', 'b', 'c', 'd'})
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
b := make([]byte, 10)
|
||||
nBytes, err := conn.Read(b)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
assert.Bytes(xor(b[:nBytes])).Equals([]byte{'a', 'b', 'c', 'd'})
|
||||
|
||||
conn.Close()
|
||||
tcpServer.Close()
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package proxyman
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/proxy"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
229
app/router/condition.go
Normal file
229
app/router/condition.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
)
|
||||
|
||||
type Condition interface {
|
||||
Apply(session *proxy.SessionInfo) bool
|
||||
}
|
||||
|
||||
type ConditionChan []Condition
|
||||
|
||||
func NewConditionChan() *ConditionChan {
|
||||
var condChan ConditionChan = make([]Condition, 0, 8)
|
||||
return &condChan
|
||||
}
|
||||
|
||||
func (this *ConditionChan) Add(cond Condition) *ConditionChan {
|
||||
*this = append(*this, cond)
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *ConditionChan) Apply(session *proxy.SessionInfo) bool {
|
||||
for _, cond := range *this {
|
||||
if !cond.Apply(session) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *ConditionChan) Len() int {
|
||||
return len(*this)
|
||||
}
|
||||
|
||||
type AnyCondition []Condition
|
||||
|
||||
func NewAnyCondition() *AnyCondition {
|
||||
var anyCond AnyCondition = make([]Condition, 0, 8)
|
||||
return &anyCond
|
||||
}
|
||||
|
||||
func (this *AnyCondition) Add(cond Condition) *AnyCondition {
|
||||
*this = append(*this, cond)
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *AnyCondition) Apply(session *proxy.SessionInfo) bool {
|
||||
for _, cond := range *this {
|
||||
if cond.Apply(session) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *AnyCondition) Len() int {
|
||||
return len(*this)
|
||||
}
|
||||
|
||||
type PlainDomainMatcher struct {
|
||||
pattern string
|
||||
}
|
||||
|
||||
func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
|
||||
return &PlainDomainMatcher{
|
||||
pattern: pattern,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *PlainDomainMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
dest := session.Destination
|
||||
if !dest.Address.Family().IsDomain() {
|
||||
return false
|
||||
}
|
||||
domain := dest.Address.Domain()
|
||||
return strings.Contains(domain, this.pattern)
|
||||
}
|
||||
|
||||
type RegexpDomainMatcher struct {
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
|
||||
r, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RegexpDomainMatcher{
|
||||
pattern: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (this *RegexpDomainMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
dest := session.Destination
|
||||
if !dest.Address.Family().IsDomain() {
|
||||
return false
|
||||
}
|
||||
domain := dest.Address.Domain()
|
||||
return this.pattern.MatchString(strings.ToLower(domain))
|
||||
}
|
||||
|
||||
type CIDRMatcher struct {
|
||||
cidr *net.IPNet
|
||||
onSource bool
|
||||
}
|
||||
|
||||
func NewCIDRMatcher(ip []byte, mask uint32, onSource bool) (*CIDRMatcher, error) {
|
||||
cidr := &net.IPNet{
|
||||
IP: net.IP(ip),
|
||||
Mask: net.CIDRMask(int(mask), len(ip)),
|
||||
}
|
||||
return &CIDRMatcher{
|
||||
cidr: cidr,
|
||||
onSource: onSource,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (this *CIDRMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
dest := session.Destination
|
||||
if this.onSource {
|
||||
dest = session.Source
|
||||
}
|
||||
if !dest.Address.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
|
||||
return false
|
||||
}
|
||||
return this.cidr.Contains(dest.Address.IP())
|
||||
}
|
||||
|
||||
type IPv4Matcher struct {
|
||||
ipv4net *v2net.IPNet
|
||||
onSource bool
|
||||
}
|
||||
|
||||
func NewIPv4Matcher(ipnet *v2net.IPNet, onSource bool) *IPv4Matcher {
|
||||
return &IPv4Matcher{
|
||||
ipv4net: ipnet,
|
||||
onSource: onSource,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *IPv4Matcher) Apply(session *proxy.SessionInfo) bool {
|
||||
dest := session.Destination
|
||||
if this.onSource {
|
||||
dest = session.Source
|
||||
}
|
||||
if !dest.Address.Family().Either(v2net.AddressFamilyIPv4) {
|
||||
return false
|
||||
}
|
||||
return this.ipv4net.Contains(dest.Address.IP())
|
||||
}
|
||||
|
||||
type PortMatcher struct {
|
||||
port v2net.PortRange
|
||||
}
|
||||
|
||||
func NewPortMatcher(portRange v2net.PortRange) *PortMatcher {
|
||||
return &PortMatcher{
|
||||
port: portRange,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *PortMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
return this.port.Contains(session.Destination.Port)
|
||||
}
|
||||
|
||||
type NetworkMatcher struct {
|
||||
network *v2net.NetworkList
|
||||
}
|
||||
|
||||
func NewNetworkMatcher(network *v2net.NetworkList) *NetworkMatcher {
|
||||
return &NetworkMatcher{
|
||||
network: network,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *NetworkMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
return this.network.HasNetwork(session.Destination.Network)
|
||||
}
|
||||
|
||||
type UserMatcher struct {
|
||||
user []string
|
||||
}
|
||||
|
||||
func NewUserMatcher(users []string) *UserMatcher {
|
||||
return &UserMatcher{
|
||||
user: users,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *UserMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
if session.User == nil {
|
||||
return false
|
||||
}
|
||||
for _, u := range this.user {
|
||||
if u == session.User.Email {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type InboundTagMatcher struct {
|
||||
tags []string
|
||||
}
|
||||
|
||||
func NewInboundTagMatcher(tags []string) *InboundTagMatcher {
|
||||
return &InboundTagMatcher{
|
||||
tags: tags,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *InboundTagMatcher) Apply(session *proxy.SessionInfo) bool {
|
||||
if session.Inbound == nil || len(session.Inbound.Tag) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, t := range this.tags {
|
||||
if t == session.Inbound.Tag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -1,6 +1,126 @@
|
||||
package router
|
||||
|
||||
type Config struct {
|
||||
Strategy string
|
||||
Settings interface{}
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
)
|
||||
|
||||
type Rule struct {
|
||||
Tag string
|
||||
Condition Condition
|
||||
}
|
||||
|
||||
func (this *Rule) Apply(session *proxy.SessionInfo) bool {
|
||||
return this.Condition.Apply(session)
|
||||
}
|
||||
|
||||
func (this *RoutingRule) BuildCondition() (Condition, error) {
|
||||
conds := NewConditionChan()
|
||||
|
||||
if len(this.Domain) > 0 {
|
||||
anyCond := NewAnyCondition()
|
||||
for _, domain := range this.Domain {
|
||||
if domain.Type == Domain_Plain {
|
||||
anyCond.Add(NewPlainDomainMatcher(domain.Value))
|
||||
} else {
|
||||
matcher, err := NewRegexpDomainMatcher(domain.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
anyCond.Add(matcher)
|
||||
}
|
||||
}
|
||||
conds.Add(anyCond)
|
||||
}
|
||||
|
||||
if len(this.Cidr) > 0 {
|
||||
ipv4Net := v2net.NewIPNet()
|
||||
ipv6Cond := NewAnyCondition()
|
||||
hasIpv6 := false
|
||||
|
||||
for _, ip := range this.Cidr {
|
||||
switch len(ip.Ip) {
|
||||
case net.IPv4len:
|
||||
ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
|
||||
case net.IPv6len:
|
||||
hasIpv6 = true
|
||||
matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipv6Cond.Add(matcher)
|
||||
default:
|
||||
return nil, errors.New("Router: Invalid IP length.")
|
||||
}
|
||||
}
|
||||
|
||||
if !ipv4Net.IsEmpty() && hasIpv6 {
|
||||
cond := NewAnyCondition()
|
||||
cond.Add(NewIPv4Matcher(ipv4Net, false))
|
||||
cond.Add(ipv6Cond)
|
||||
conds.Add(cond)
|
||||
} else if !ipv4Net.IsEmpty() {
|
||||
conds.Add(NewIPv4Matcher(ipv4Net, false))
|
||||
} else if hasIpv6 {
|
||||
conds.Add(ipv6Cond)
|
||||
}
|
||||
}
|
||||
|
||||
if this.PortRange != nil {
|
||||
conds.Add(NewPortMatcher(*this.PortRange))
|
||||
}
|
||||
|
||||
if this.NetworkList != nil {
|
||||
conds.Add(NewNetworkMatcher(this.NetworkList))
|
||||
}
|
||||
|
||||
if len(this.SourceCidr) > 0 {
|
||||
ipv4Net := v2net.NewIPNet()
|
||||
ipv6Cond := NewAnyCondition()
|
||||
hasIpv6 := false
|
||||
|
||||
for _, ip := range this.SourceCidr {
|
||||
switch len(ip.Ip) {
|
||||
case net.IPv4len:
|
||||
ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
|
||||
case net.IPv6len:
|
||||
hasIpv6 = true
|
||||
matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipv6Cond.Add(matcher)
|
||||
default:
|
||||
return nil, errors.New("Router: Invalid IP length.")
|
||||
}
|
||||
}
|
||||
|
||||
if !ipv4Net.IsEmpty() && hasIpv6 {
|
||||
cond := NewAnyCondition()
|
||||
cond.Add(NewIPv4Matcher(ipv4Net, true))
|
||||
cond.Add(ipv6Cond)
|
||||
conds.Add(cond)
|
||||
} else if !ipv4Net.IsEmpty() {
|
||||
conds.Add(NewIPv4Matcher(ipv4Net, true))
|
||||
} else if hasIpv6 {
|
||||
conds.Add(ipv6Cond)
|
||||
}
|
||||
}
|
||||
|
||||
if len(this.UserEmail) > 0 {
|
||||
conds.Add(NewUserMatcher(this.UserEmail))
|
||||
}
|
||||
|
||||
if len(this.InboundTag) > 0 {
|
||||
conds.Add(NewInboundTagMatcher(this.InboundTag))
|
||||
}
|
||||
|
||||
if conds.Len() == 0 {
|
||||
return nil, errors.New("Router: This rule has no effective fields.")
|
||||
}
|
||||
|
||||
return conds, nil
|
||||
}
|
||||
|
||||
227
app/router/config.pb.go
Normal file
227
app/router/config.pb.go
Normal file
@@ -0,0 +1,227 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/app/router/config.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package router is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
v2ray.com/core/app/router/config.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Domain
|
||||
CIDR
|
||||
RoutingRule
|
||||
Config
|
||||
*/
|
||||
package router
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import v2ray_core_common_net "v2ray.com/core/common/net"
|
||||
import v2ray_core_common_net1 "v2ray.com/core/common/net"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Type of domain value.
|
||||
type Domain_Type int32
|
||||
|
||||
const (
|
||||
// The value is used as is.
|
||||
Domain_Plain Domain_Type = 0
|
||||
// The value is used as a regular expression.
|
||||
Domain_Regex Domain_Type = 1
|
||||
)
|
||||
|
||||
var Domain_Type_name = map[int32]string{
|
||||
0: "Plain",
|
||||
1: "Regex",
|
||||
}
|
||||
var Domain_Type_value = map[string]int32{
|
||||
"Plain": 0,
|
||||
"Regex": 1,
|
||||
}
|
||||
|
||||
func (x Domain_Type) String() string {
|
||||
return proto.EnumName(Domain_Type_name, int32(x))
|
||||
}
|
||||
func (Domain_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
|
||||
|
||||
type Config_DomainStrategy int32
|
||||
|
||||
const (
|
||||
// Use domain as is.
|
||||
Config_AsIs Config_DomainStrategy = 0
|
||||
// Always resolve IP for domains.
|
||||
Config_UseIp Config_DomainStrategy = 1
|
||||
// Resolve to IP if the domain doesn't match any rules.
|
||||
Config_IpIfNonMatch Config_DomainStrategy = 2
|
||||
)
|
||||
|
||||
var Config_DomainStrategy_name = map[int32]string{
|
||||
0: "AsIs",
|
||||
1: "UseIp",
|
||||
2: "IpIfNonMatch",
|
||||
}
|
||||
var Config_DomainStrategy_value = map[string]int32{
|
||||
"AsIs": 0,
|
||||
"UseIp": 1,
|
||||
"IpIfNonMatch": 2,
|
||||
}
|
||||
|
||||
func (x Config_DomainStrategy) String() string {
|
||||
return proto.EnumName(Config_DomainStrategy_name, int32(x))
|
||||
}
|
||||
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} }
|
||||
|
||||
// Domain for routing decision.
|
||||
type Domain struct {
|
||||
// Domain matching type.
|
||||
Type Domain_Type `protobuf:"varint,1,opt,name=type,enum=v2ray.core.app.router.Domain_Type" json:"type,omitempty"`
|
||||
// Domain value.
|
||||
Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Domain) Reset() { *m = Domain{} }
|
||||
func (m *Domain) String() string { return proto.CompactTextString(m) }
|
||||
func (*Domain) ProtoMessage() {}
|
||||
func (*Domain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
// IP for routing decision, in CIDR form.
|
||||
type CIDR struct {
|
||||
// IP address, should be either 4 or 16 bytes.
|
||||
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||
// Number of leading ones in the network mask.
|
||||
Prefix uint32 `protobuf:"varint,2,opt,name=prefix" json:"prefix,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CIDR) Reset() { *m = CIDR{} }
|
||||
func (m *CIDR) String() string { return proto.CompactTextString(m) }
|
||||
func (*CIDR) ProtoMessage() {}
|
||||
func (*CIDR) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
type RoutingRule struct {
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"`
|
||||
Domain []*Domain `protobuf:"bytes,2,rep,name=domain" json:"domain,omitempty"`
|
||||
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr" json:"cidr,omitempty"`
|
||||
PortRange *v2ray_core_common_net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange" json:"port_range,omitempty"`
|
||||
NetworkList *v2ray_core_common_net1.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList" json:"network_list,omitempty"`
|
||||
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr" json:"source_cidr,omitempty"`
|
||||
UserEmail []string `protobuf:"bytes,7,rep,name=user_email,json=userEmail" json:"user_email,omitempty"`
|
||||
InboundTag []string `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag" json:"inbound_tag,omitempty"`
|
||||
}
|
||||
|
||||
func (m *RoutingRule) Reset() { *m = RoutingRule{} }
|
||||
func (m *RoutingRule) String() string { return proto.CompactTextString(m) }
|
||||
func (*RoutingRule) ProtoMessage() {}
|
||||
func (*RoutingRule) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *RoutingRule) GetDomain() []*Domain {
|
||||
if m != nil {
|
||||
return m.Domain
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RoutingRule) GetCidr() []*CIDR {
|
||||
if m != nil {
|
||||
return m.Cidr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RoutingRule) GetPortRange() *v2ray_core_common_net.PortRange {
|
||||
if m != nil {
|
||||
return m.PortRange
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RoutingRule) GetNetworkList() *v2ray_core_common_net1.NetworkList {
|
||||
if m != nil {
|
||||
return m.NetworkList
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RoutingRule) GetSourceCidr() []*CIDR {
|
||||
if m != nil {
|
||||
return m.SourceCidr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,enum=v2ray.core.app.router.Config_DomainStrategy" json:"domain_strategy,omitempty"`
|
||||
Rule []*RoutingRule `protobuf:"bytes,2,rep,name=rule" json:"rule,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Config) Reset() { *m = Config{} }
|
||||
func (m *Config) String() string { return proto.CompactTextString(m) }
|
||||
func (*Config) ProtoMessage() {}
|
||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *Config) GetRule() []*RoutingRule {
|
||||
if m != nil {
|
||||
return m.Rule
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Domain)(nil), "v2ray.core.app.router.Domain")
|
||||
proto.RegisterType((*CIDR)(nil), "v2ray.core.app.router.CIDR")
|
||||
proto.RegisterType((*RoutingRule)(nil), "v2ray.core.app.router.RoutingRule")
|
||||
proto.RegisterType((*Config)(nil), "v2ray.core.app.router.Config")
|
||||
proto.RegisterEnum("v2ray.core.app.router.Domain_Type", Domain_Type_name, Domain_Type_value)
|
||||
proto.RegisterEnum("v2ray.core.app.router.Config_DomainStrategy", Config_DomainStrategy_name, Config_DomainStrategy_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/app/router/config.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 520 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x93, 0xd1, 0x6e, 0xd3, 0x3e,
|
||||
0x14, 0xc6, 0xff, 0x69, 0xb3, 0xfc, 0x97, 0x93, 0x51, 0x22, 0x0b, 0x50, 0x18, 0x4c, 0x44, 0x11,
|
||||
0x82, 0x5e, 0xa0, 0x04, 0x15, 0x01, 0x37, 0x48, 0x88, 0x75, 0xbb, 0xa8, 0x04, 0x53, 0x65, 0xb6,
|
||||
0x1b, 0x6e, 0x22, 0x2f, 0x75, 0x83, 0x45, 0x62, 0x5b, 0x8e, 0x33, 0xd6, 0x87, 0xe0, 0xdd, 0x78,
|
||||
0x24, 0x64, 0x3b, 0x13, 0x1b, 0x5a, 0xe1, 0xce, 0xe7, 0xf4, 0xf7, 0x1d, 0x7f, 0x3d, 0xfe, 0x02,
|
||||
0xcf, 0x2e, 0x66, 0x8a, 0x6c, 0xf2, 0x4a, 0xb4, 0x45, 0x25, 0x14, 0x2d, 0x88, 0x94, 0x85, 0x12,
|
||||
0xbd, 0xa6, 0xaa, 0xa8, 0x04, 0x5f, 0xb3, 0x3a, 0x97, 0x4a, 0x68, 0x81, 0xee, 0x5f, 0x71, 0x8a,
|
||||
0xe6, 0x44, 0xca, 0xdc, 0x31, 0xfb, 0x4f, 0xff, 0x90, 0x57, 0xa2, 0x6d, 0x05, 0x2f, 0x38, 0xd5,
|
||||
0x85, 0x14, 0x4a, 0x3b, 0xf1, 0xfe, 0xf3, 0xed, 0x14, 0xa7, 0xfa, 0xbb, 0x50, 0xdf, 0x1c, 0x98,
|
||||
0x69, 0x08, 0x8e, 0x44, 0x4b, 0x18, 0x47, 0x6f, 0xc0, 0xd7, 0x1b, 0x49, 0x13, 0x2f, 0xf5, 0xa6,
|
||||
0x93, 0x59, 0x96, 0xdf, 0x7a, 0x7d, 0xee, 0xe0, 0xfc, 0x74, 0x23, 0x29, 0xb6, 0x3c, 0xba, 0x07,
|
||||
0x3b, 0x17, 0xa4, 0xe9, 0x69, 0x32, 0x4a, 0xbd, 0x69, 0x88, 0x5d, 0x91, 0x3d, 0x06, 0xdf, 0x30,
|
||||
0x28, 0x84, 0x9d, 0x65, 0x43, 0x18, 0x8f, 0xff, 0x33, 0x47, 0x4c, 0x6b, 0x7a, 0x19, 0x7b, 0x59,
|
||||
0x0e, 0xfe, 0x7c, 0x71, 0x84, 0xd1, 0x04, 0x46, 0x4c, 0xda, 0x1b, 0xf7, 0xf0, 0x88, 0x49, 0xf4,
|
||||
0x00, 0x02, 0xa9, 0xe8, 0x9a, 0x5d, 0xda, 0x61, 0x77, 0xf0, 0x50, 0x65, 0x3f, 0xc6, 0x10, 0x61,
|
||||
0xd1, 0x6b, 0xc6, 0x6b, 0xdc, 0x37, 0x14, 0xc5, 0x30, 0xd6, 0xa4, 0xb6, 0xc2, 0x10, 0x9b, 0x23,
|
||||
0x7a, 0x0d, 0xc1, 0xca, 0x5a, 0x4b, 0x46, 0xe9, 0x78, 0x1a, 0xcd, 0x0e, 0xfe, 0xea, 0x1f, 0x0f,
|
||||
0x30, 0x2a, 0xc0, 0xaf, 0xd8, 0x4a, 0x25, 0x63, 0x2b, 0x7a, 0xb4, 0x45, 0x64, 0xbc, 0x62, 0x0b,
|
||||
0xa2, 0xf7, 0x00, 0x66, 0xcd, 0xa5, 0x22, 0xbc, 0xa6, 0x89, 0x9f, 0x7a, 0xd3, 0x68, 0x96, 0x5e,
|
||||
0x97, 0xb9, 0x4d, 0xe7, 0x9c, 0xea, 0x7c, 0x29, 0x94, 0xc6, 0x86, 0xc3, 0xa1, 0xbc, 0x3a, 0xa2,
|
||||
0x63, 0xd8, 0x1b, 0x5e, 0xa0, 0x6c, 0x58, 0xa7, 0x93, 0x1d, 0x3b, 0x22, 0xdb, 0x32, 0xe2, 0xc4,
|
||||
0xa1, 0x1f, 0x59, 0xa7, 0x71, 0xc4, 0x7f, 0x17, 0xe8, 0x1d, 0x44, 0x9d, 0xe8, 0x55, 0x45, 0x4b,
|
||||
0xeb, 0x3f, 0xf8, 0xb7, 0x7f, 0x70, 0xfc, 0xdc, 0xfc, 0x8b, 0x03, 0x80, 0xbe, 0xa3, 0xaa, 0xa4,
|
||||
0x2d, 0x61, 0x4d, 0xf2, 0x7f, 0x3a, 0x9e, 0x86, 0x38, 0x34, 0x9d, 0x63, 0xd3, 0x40, 0x4f, 0x20,
|
||||
0x62, 0xfc, 0x5c, 0xf4, 0x7c, 0x55, 0x9a, 0x35, 0xef, 0xda, 0xdf, 0x61, 0x68, 0x9d, 0x92, 0x3a,
|
||||
0xfb, 0xe9, 0x41, 0x30, 0xb7, 0x61, 0x45, 0x67, 0x70, 0xd7, 0xed, 0xb2, 0xec, 0xb4, 0x22, 0x9a,
|
||||
0xd6, 0x9b, 0x21, 0x41, 0x2f, 0xb6, 0x99, 0x71, 0x21, 0x77, 0x0f, 0xf1, 0x79, 0xd0, 0xe0, 0xc9,
|
||||
0xea, 0x46, 0x6d, 0xd2, 0xa8, 0xfa, 0x86, 0x0e, 0xaf, 0xb9, 0x2d, 0x8d, 0xd7, 0x32, 0x81, 0x2d,
|
||||
0x9f, 0xbd, 0x85, 0xc9, 0xcd, 0xc9, 0x68, 0x17, 0xfc, 0x0f, 0xdd, 0xa2, 0x73, 0x01, 0x3c, 0xeb,
|
||||
0xe8, 0x42, 0xc6, 0x1e, 0x8a, 0x61, 0x6f, 0x21, 0x17, 0xeb, 0x13, 0xc1, 0x3f, 0x11, 0x5d, 0x7d,
|
||||
0x8d, 0x47, 0x87, 0x2f, 0xe1, 0x61, 0x25, 0xda, 0xdb, 0xef, 0x39, 0x8c, 0x9c, 0xe9, 0xa5, 0xf9,
|
||||
0x64, 0xbe, 0x04, 0xae, 0x79, 0x1e, 0xd8, 0x2f, 0xe8, 0xd5, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xe4, 0x89, 0x6f, 0xa7, 0xd1, 0x03, 0x00, 0x00,
|
||||
}
|
||||
61
app/router/config.proto
Normal file
61
app/router/config.proto
Normal file
@@ -0,0 +1,61 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.app.router;
|
||||
option go_package = "router";
|
||||
option java_package = "com.v2ray.core.app.router";
|
||||
option java_outer_classname = "ConfigProto";
|
||||
|
||||
import "v2ray.com/core/common/net/port.proto";
|
||||
import "v2ray.com/core/common/net/network.proto";
|
||||
|
||||
// Domain for routing decision.
|
||||
message Domain {
|
||||
// Type of domain value.
|
||||
enum Type {
|
||||
// The value is used as is.
|
||||
Plain = 0;
|
||||
// The value is used as a regular expression.
|
||||
Regex = 1;
|
||||
}
|
||||
|
||||
// Domain matching type.
|
||||
Type type = 1;
|
||||
|
||||
// Domain value.
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
// IP for routing decision, in CIDR form.
|
||||
message CIDR {
|
||||
// IP address, should be either 4 or 16 bytes.
|
||||
bytes ip = 1;
|
||||
|
||||
// Number of leading ones in the network mask.
|
||||
uint32 prefix = 2;
|
||||
}
|
||||
|
||||
message RoutingRule {
|
||||
string tag = 1;
|
||||
repeated Domain domain = 2;
|
||||
repeated CIDR cidr = 3;
|
||||
v2ray.core.common.net.PortRange port_range = 4;
|
||||
v2ray.core.common.net.NetworkList network_list = 5;
|
||||
repeated CIDR source_cidr = 6;
|
||||
repeated string user_email = 7;
|
||||
repeated string inbound_tag = 8;
|
||||
}
|
||||
|
||||
message Config {
|
||||
enum DomainStrategy {
|
||||
// Use domain as is.
|
||||
AsIs = 0;
|
||||
|
||||
// Always resolve IP for domains.
|
||||
UseIp = 1;
|
||||
|
||||
// Resolve to IP if the domain doesn't match any rules.
|
||||
IpIfNonMatch = 2;
|
||||
}
|
||||
DomainStrategy domain_strategy = 1;
|
||||
repeated RoutingRule rule = 2;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type ConfigObjectCreator func([]byte) (interface{}, error)
|
||||
|
||||
var (
|
||||
configCache map[string]ConfigObjectCreator
|
||||
|
||||
ErrRouterNotFound = errors.New("Router not found.")
|
||||
)
|
||||
|
||||
func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
|
||||
// TODO: check strategy
|
||||
configCache[strategy] = creator
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateRouterConfig(strategy string, data []byte) (interface{}, error) {
|
||||
creator, found := configCache[strategy]
|
||||
if !found {
|
||||
return nil, ErrRouterNotFound
|
||||
}
|
||||
return creator(data)
|
||||
}
|
||||
|
||||
func init() {
|
||||
configCache = make(map[string]ConfigObjectCreator)
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package router
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
)
|
||||
|
||||
func (this *Config) UnmarshalJSON(data []byte) error {
|
||||
type JsonConfig struct {
|
||||
Strategy string `json:"strategy"`
|
||||
Settings json.RawMessage `json:"settings"`
|
||||
}
|
||||
jsonConfig := new(JsonConfig)
|
||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
settings, err := CreateRouterConfig(jsonConfig.Strategy, []byte(jsonConfig.Settings))
|
||||
if err != nil {
|
||||
log.Error("Router: Failed to load router settings: ", err)
|
||||
return err
|
||||
}
|
||||
this.Strategy = jsonConfig.Strategy
|
||||
this.Settings = settings
|
||||
return nil
|
||||
}
|
||||
@@ -1,37 +1,131 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/common"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"errors"
|
||||
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/app/dns"
|
||||
"v2ray.com/core/common/loader"
|
||||
"v2ray.com/core/common/log"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
)
|
||||
|
||||
const (
|
||||
APP_ID = app.ID(3)
|
||||
)
|
||||
|
||||
type Router interface {
|
||||
common.Releasable
|
||||
TakeDetour(v2net.Destination) (string, error)
|
||||
}
|
||||
|
||||
type RouterFactory interface {
|
||||
Create(rawConfig interface{}, space app.Space) (Router, error)
|
||||
}
|
||||
|
||||
var (
|
||||
routerCache = make(map[string]RouterFactory)
|
||||
ErrInvalidRule = errors.New("Invalid Rule")
|
||||
ErrNoRuleApplicable = errors.New("No rule applicable")
|
||||
)
|
||||
|
||||
func RegisterRouter(name string, factory RouterFactory) error {
|
||||
// TODO: check name
|
||||
routerCache[name] = factory
|
||||
return nil
|
||||
type Router struct {
|
||||
domainStrategy Config_DomainStrategy
|
||||
rules []Rule
|
||||
// cache *RoutingTable
|
||||
dnsServer dns.Server
|
||||
}
|
||||
|
||||
func CreateRouter(name string, rawConfig interface{}, space app.Space) (Router, error) {
|
||||
if factory, found := routerCache[name]; found {
|
||||
return factory.Create(rawConfig, space)
|
||||
func NewRouter(config *Config, space app.Space) *Router {
|
||||
r := &Router{
|
||||
domainStrategy: config.DomainStrategy,
|
||||
//cache: NewRoutingTable(),
|
||||
rules: make([]Rule, len(config.Rule)),
|
||||
}
|
||||
return nil, ErrRouterNotFound
|
||||
|
||||
space.InitializeApplication(func() error {
|
||||
for idx, rule := range config.Rule {
|
||||
r.rules[idx].Tag = rule.Tag
|
||||
cond, err := rule.BuildCondition()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.rules[idx].Condition = cond
|
||||
}
|
||||
|
||||
if !space.HasApp(dns.APP_ID) {
|
||||
log.Error("Router: DNS is not found in the space.")
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func (this *Router) Release() {
|
||||
|
||||
}
|
||||
|
||||
// Private: Visible for testing.
|
||||
func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
|
||||
ips := this.dnsServer.Get(dest.Address.Domain())
|
||||
if len(ips) == 0 {
|
||||
return nil
|
||||
}
|
||||
dests := make([]v2net.Destination, len(ips))
|
||||
for idx, ip := range ips {
|
||||
if dest.Network == v2net.Network_TCP {
|
||||
dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port)
|
||||
} else {
|
||||
dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port)
|
||||
}
|
||||
}
|
||||
return dests
|
||||
}
|
||||
|
||||
func (this *Router) takeDetourWithoutCache(session *proxy.SessionInfo) (string, error) {
|
||||
for _, rule := range this.rules {
|
||||
if rule.Apply(session) {
|
||||
return rule.Tag, nil
|
||||
}
|
||||
}
|
||||
dest := session.Destination
|
||||
if this.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() {
|
||||
log.Info("Router: Looking up IP for ", dest)
|
||||
ipDests := this.ResolveIP(dest)
|
||||
if ipDests != nil {
|
||||
for _, ipDest := range ipDests {
|
||||
log.Info("Router: Trying IP ", ipDest)
|
||||
for _, rule := range this.rules {
|
||||
if rule.Apply(&proxy.SessionInfo{
|
||||
Source: session.Source,
|
||||
Destination: ipDest,
|
||||
User: session.User,
|
||||
}) {
|
||||
return rule.Tag, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", ErrNoRuleApplicable
|
||||
}
|
||||
|
||||
func (this *Router) TakeDetour(session *proxy.SessionInfo) (string, error) {
|
||||
//destStr := dest.String()
|
||||
//found, tag, err := this.cache.Get(destStr)
|
||||
//if !found {
|
||||
tag, err := this.takeDetourWithoutCache(session)
|
||||
//this.cache.Set(destStr, tag, err)
|
||||
return tag, err
|
||||
//}
|
||||
//return tag, err
|
||||
}
|
||||
|
||||
type RouterFactory struct{}
|
||||
|
||||
func (RouterFactory) Create(space app.Space, config interface{}) (app.Application, error) {
|
||||
router := NewRouter(config.(*Config), space)
|
||||
return router, nil
|
||||
}
|
||||
|
||||
func (RouterFactory) AppId() app.ID {
|
||||
return APP_ID
|
||||
}
|
||||
|
||||
func init() {
|
||||
app.RegisterApplicationFactory(loader.GetType(new(Config)), RouterFactory{})
|
||||
}
|
||||
|
||||
42
app/router/router_test.go
Normal file
42
app/router/router_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package router_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"v2ray.com/core/app"
|
||||
"v2ray.com/core/app/dispatcher"
|
||||
dispatchers "v2ray.com/core/app/dispatcher/impl"
|
||||
"v2ray.com/core/app/dns"
|
||||
"v2ray.com/core/app/proxyman"
|
||||
. "v2ray.com/core/app/router"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestSimpleRouter(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
config := &Config{
|
||||
Rule: []*RoutingRule{
|
||||
{
|
||||
Tag: "test",
|
||||
NetworkList: &v2net.NetworkList{
|
||||
Network: []v2net.Network{v2net.Network_TCP},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
space := app.NewSpace()
|
||||
space.BindApp(dns.APP_ID, dns.NewCacheServer(space, &dns.Config{}))
|
||||
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager())
|
||||
r := NewRouter(config, space)
|
||||
space.BindApp(APP_ID, r)
|
||||
assert.Error(space.Initialize()).IsNil()
|
||||
|
||||
tag, err := r.TakeDetour(&proxy.SessionInfo{Destination: v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80)})
|
||||
assert.Error(err).IsNil()
|
||||
assert.String(tag).Equals("test")
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package rules
|
||||
package router
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -1,10 +0,0 @@
|
||||
package rules
|
||||
|
||||
//go:generate go run chinaip_gen.go
|
||||
|
||||
func NewChinaIPRule(tag string) *Rule {
|
||||
return &Rule{
|
||||
Tag: tag,
|
||||
Condition: NewIPv4Matcher(chinaIPNet),
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
// +build generate
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
)
|
||||
|
||||
const (
|
||||
apnicFile = "http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
resp, err := http.Get(apnicFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
panic(fmt.Errorf("Unexpected status %d", resp.StatusCode))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
scanner := bufio.NewScanner(resp.Body)
|
||||
|
||||
ipNet := v2net.NewIPNet()
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
line = strings.TrimSpace(line)
|
||||
parts := strings.Split(line, "|")
|
||||
if len(parts) < 5 {
|
||||
continue
|
||||
}
|
||||
if strings.ToLower(parts[1]) != "cn" || strings.ToLower(parts[2]) != "ipv4" {
|
||||
continue
|
||||
}
|
||||
ip := parts[3]
|
||||
count, err := strconv.Atoi(parts[4])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
mask := 32 - int(math.Floor(math.Log2(float64(count))+0.5))
|
||||
cidr := fmt.Sprintf("%s/%d", ip, mask)
|
||||
_, t, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ipNet.Add(t)
|
||||
}
|
||||
dump := ipNet.Serialize()
|
||||
|
||||
file, err := os.OpenFile("chinaip_init.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate chinaip_init.go: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fmt.Fprintln(file, "package rules")
|
||||
fmt.Fprintln(file, "import (")
|
||||
fmt.Fprintln(file, "v2net \"github.com/v2ray/v2ray-core/common/net\"")
|
||||
fmt.Fprintln(file, ")")
|
||||
|
||||
fmt.Fprintln(file, "var (")
|
||||
fmt.Fprintln(file, "chinaIPNet *v2net.IPNet")
|
||||
fmt.Fprintln(file, ")")
|
||||
|
||||
fmt.Fprintln(file, "func init() {")
|
||||
|
||||
fmt.Fprintln(file, "chinaIPNet = v2net.NewIPNetInitialValue(map[uint32]byte {")
|
||||
for i := 0; i < len(dump); i += 2 {
|
||||
fmt.Fprintln(file, dump[i], ": ", dump[i+1], ",")
|
||||
}
|
||||
fmt.Fprintln(file, "})")
|
||||
fmt.Fprintln(file, "}")
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
)
|
||||
|
||||
func parseChinaIPRule(data []byte) (*Rule, error) {
|
||||
rawRule := new(JsonRule)
|
||||
err := json.Unmarshal(data, rawRule)
|
||||
if err != nil {
|
||||
log.Error("Router: Invalid router rule: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return NewChinaIPRule(rawRule.OutboundTag), nil
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package rules_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/app/router/rules"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestChinaIPJson(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rule := ParseRule([]byte(`{
|
||||
"type": "chinaip",
|
||||
"outboundTag": "x"
|
||||
}`))
|
||||
assert.String(rule.Tag).Equals("x")
|
||||
assert.Bool(rule.Apply(makeDestination("121.14.1.189"))).IsTrue() // sina.com.cn
|
||||
assert.Bool(rule.Apply(makeDestination("101.226.103.106"))).IsTrue() // qq.com
|
||||
assert.Bool(rule.Apply(makeDestination("115.239.210.36"))).IsTrue() // image.baidu.com
|
||||
assert.Bool(rule.Apply(makeDestination("120.135.126.1"))).IsTrue()
|
||||
|
||||
assert.Bool(rule.Apply(makeDestination("8.8.8.8"))).IsFalse()
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package rules_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/app/router/rules"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func makeDestination(ip string) v2net.Destination {
|
||||
return v2net.TCPDestination(v2net.IPAddress(net.ParseIP(ip)), 80)
|
||||
}
|
||||
|
||||
func TestChinaIP(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rule := NewChinaIPRule("tag")
|
||||
assert.Bool(rule.Apply(makeDestination("121.14.1.189"))).IsTrue() // sina.com.cn
|
||||
assert.Bool(rule.Apply(makeDestination("101.226.103.106"))).IsTrue() // qq.com
|
||||
assert.Bool(rule.Apply(makeDestination("115.239.210.36"))).IsTrue() // image.baidu.com
|
||||
assert.Bool(rule.Apply(makeDestination("120.135.126.1"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDestination("101.201.173.126"))).IsTrue()
|
||||
|
||||
assert.Bool(rule.Apply(makeDestination("8.8.8.8"))).IsFalse()
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
)
|
||||
|
||||
func parseChinaSitesRule(data []byte) (*Rule, error) {
|
||||
rawRule := new(JsonRule)
|
||||
err := json.Unmarshal(data, rawRule)
|
||||
if err != nil {
|
||||
log.Error("Router: Invalid router rule: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return &Rule{
|
||||
Tag: rawRule.OutboundTag,
|
||||
Condition: chinaSitesConds,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package rules_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/app/router/rules"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestChinaSitesJson(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rule := ParseRule([]byte(`{
|
||||
"type": "chinasites",
|
||||
"outboundTag": "y"
|
||||
}`))
|
||||
assert.String(rule.Tag).Equals("y")
|
||||
assert.Bool(rule.Apply(makeDomainDestination("v.qq.com"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDomainDestination("www.163.com"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDomainDestination("ngacn.cc"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDomainDestination("12306.cn"))).IsTrue()
|
||||
|
||||
assert.Bool(rule.Apply(makeDomainDestination("v2ray.com"))).IsFalse()
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package rules_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/app/router/rules"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func makeDomainDestination(domain string) v2net.Destination {
|
||||
return v2net.TCPDestination(v2net.DomainAddress(domain), 80)
|
||||
}
|
||||
|
||||
func TestChinaSites(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rule := NewChinaSitesRule("tag")
|
||||
assert.Bool(rule.Apply(makeDomainDestination("v.qq.com"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDomainDestination("www.163.com"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDomainDestination("ngacn.cc"))).IsTrue()
|
||||
assert.Bool(rule.Apply(makeDomainDestination("12306.cn"))).IsTrue()
|
||||
|
||||
assert.Bool(rule.Apply(makeDomainDestination("v2ray.com"))).IsFalse()
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
)
|
||||
|
||||
type Condition interface {
|
||||
Apply(dest v2net.Destination) bool
|
||||
}
|
||||
|
||||
type ConditionChan []Condition
|
||||
|
||||
func NewConditionChan() *ConditionChan {
|
||||
var condChan ConditionChan = make([]Condition, 0, 8)
|
||||
return &condChan
|
||||
}
|
||||
|
||||
func (this *ConditionChan) Add(cond Condition) *ConditionChan {
|
||||
*this = append(*this, cond)
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *ConditionChan) Apply(dest v2net.Destination) bool {
|
||||
for _, cond := range *this {
|
||||
if !cond.Apply(dest) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (this *ConditionChan) Len() int {
|
||||
return len(*this)
|
||||
}
|
||||
|
||||
type AnyCondition []Condition
|
||||
|
||||
func NewAnyCondition() *AnyCondition {
|
||||
var anyCond AnyCondition = make([]Condition, 0, 8)
|
||||
return &anyCond
|
||||
}
|
||||
|
||||
func (this *AnyCondition) Add(cond Condition) *AnyCondition {
|
||||
*this = append(*this, cond)
|
||||
return this
|
||||
}
|
||||
|
||||
func (this *AnyCondition) Apply(dest v2net.Destination) bool {
|
||||
for _, cond := range *this {
|
||||
if cond.Apply(dest) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *AnyCondition) Len() int {
|
||||
return len(*this)
|
||||
}
|
||||
|
||||
type PlainDomainMatcher struct {
|
||||
pattern string
|
||||
}
|
||||
|
||||
func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
|
||||
return &PlainDomainMatcher{
|
||||
pattern: pattern,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().Family().IsDomain() {
|
||||
return false
|
||||
}
|
||||
domain := dest.Address().Domain()
|
||||
return strings.Contains(domain, this.pattern)
|
||||
}
|
||||
|
||||
type RegexpDomainMatcher struct {
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
|
||||
r, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RegexpDomainMatcher{
|
||||
pattern: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().Family().IsDomain() {
|
||||
return false
|
||||
}
|
||||
domain := dest.Address().Domain()
|
||||
return this.pattern.MatchString(strings.ToLower(domain))
|
||||
}
|
||||
|
||||
type CIDRMatcher struct {
|
||||
cidr *net.IPNet
|
||||
}
|
||||
|
||||
func NewCIDRMatcher(ipnet string) (*CIDRMatcher, error) {
|
||||
_, cidr, err := net.ParseCIDR(ipnet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &CIDRMatcher{
|
||||
cidr: cidr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (this *CIDRMatcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
|
||||
return false
|
||||
}
|
||||
return this.cidr.Contains(dest.Address().IP())
|
||||
}
|
||||
|
||||
type IPv4Matcher struct {
|
||||
ipv4net *v2net.IPNet
|
||||
}
|
||||
|
||||
func NewIPv4Matcher(ipnet *v2net.IPNet) *IPv4Matcher {
|
||||
return &IPv4Matcher{
|
||||
ipv4net: ipnet,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *IPv4Matcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().Family().Either(v2net.AddressFamilyIPv4) {
|
||||
return false
|
||||
}
|
||||
return this.ipv4net.Contains(dest.Address().IP())
|
||||
}
|
||||
|
||||
type PortMatcher struct {
|
||||
port v2net.PortRange
|
||||
}
|
||||
|
||||
func NewPortMatcher(portRange v2net.PortRange) *PortMatcher {
|
||||
return &PortMatcher{
|
||||
port: portRange,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *PortMatcher) Apply(dest v2net.Destination) bool {
|
||||
return this.port.Contains(dest.Port())
|
||||
}
|
||||
|
||||
type NetworkMatcher struct {
|
||||
network *v2net.NetworkList
|
||||
}
|
||||
|
||||
func NewNetworkMatcher(network *v2net.NetworkList) *NetworkMatcher {
|
||||
return &NetworkMatcher{
|
||||
network: network,
|
||||
}
|
||||
}
|
||||
|
||||
func (this *NetworkMatcher) Apply(dest v2net.Destination) bool {
|
||||
return this.network.HasNetwork(dest.Network())
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
)
|
||||
|
||||
type Rule struct {
|
||||
Tag string
|
||||
Condition Condition
|
||||
}
|
||||
|
||||
func (this *Rule) Apply(dest v2net.Destination) bool {
|
||||
return this.Condition.Apply(dest)
|
||||
}
|
||||
|
||||
type DomainStrategy int
|
||||
|
||||
var (
|
||||
DomainAsIs = DomainStrategy(0)
|
||||
AlwaysUseIP = DomainStrategy(1)
|
||||
UseIPIfNonMatch = DomainStrategy(2)
|
||||
)
|
||||
|
||||
type RouterRuleConfig struct {
|
||||
Rules []*Rule
|
||||
DomainStrategy DomainStrategy
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
router "github.com/v2ray/v2ray-core/app/router"
|
||||
"github.com/v2ray/v2ray-core/common/collect"
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
)
|
||||
|
||||
type JsonRule struct {
|
||||
Type string `json:"type"`
|
||||
OutboundTag string `json:"outboundTag"`
|
||||
}
|
||||
|
||||
func parseFieldRule(msg json.RawMessage) (*Rule, error) {
|
||||
type RawFieldRule struct {
|
||||
JsonRule
|
||||
Domain *collect.StringList `json:"domain"`
|
||||
IP *collect.StringList `json:"ip"`
|
||||
Port *v2net.PortRange `json:"port"`
|
||||
Network *v2net.NetworkList `json:"network"`
|
||||
}
|
||||
rawFieldRule := new(RawFieldRule)
|
||||
err := json.Unmarshal(msg, rawFieldRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conds := NewConditionChan()
|
||||
|
||||
if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
|
||||
anyCond := NewAnyCondition()
|
||||
for _, rawDomain := range *(rawFieldRule.Domain) {
|
||||
var matcher Condition
|
||||
if strings.HasPrefix(rawDomain, "regexp:") {
|
||||
rawMatcher, err := NewRegexpDomainMatcher(rawDomain[7:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
matcher = rawMatcher
|
||||
} else {
|
||||
matcher = NewPlainDomainMatcher(rawDomain)
|
||||
}
|
||||
anyCond.Add(matcher)
|
||||
}
|
||||
conds.Add(anyCond)
|
||||
}
|
||||
|
||||
if rawFieldRule.IP != nil && rawFieldRule.IP.Len() > 0 {
|
||||
anyCond := NewAnyCondition()
|
||||
for _, ipStr := range *(rawFieldRule.IP) {
|
||||
cidrMatcher, err := NewCIDRMatcher(ipStr)
|
||||
if err != nil {
|
||||
log.Error("Router: Invalid IP range in router rule: ", err)
|
||||
return nil, err
|
||||
}
|
||||
anyCond.Add(cidrMatcher)
|
||||
}
|
||||
conds.Add(anyCond)
|
||||
}
|
||||
if rawFieldRule.Port != nil {
|
||||
conds.Add(NewPortMatcher(*rawFieldRule.Port))
|
||||
}
|
||||
if rawFieldRule.Network != nil {
|
||||
conds.Add(NewNetworkMatcher(rawFieldRule.Network))
|
||||
}
|
||||
if conds.Len() == 0 {
|
||||
return nil, errors.New("Router: This rule has no effective fields.")
|
||||
}
|
||||
return &Rule{
|
||||
Tag: rawFieldRule.OutboundTag,
|
||||
Condition: conds,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ParseRule(msg json.RawMessage) *Rule {
|
||||
rawRule := new(JsonRule)
|
||||
err := json.Unmarshal(msg, rawRule)
|
||||
if err != nil {
|
||||
log.Error("Router: Invalid router rule: ", err)
|
||||
return nil
|
||||
}
|
||||
if rawRule.Type == "field" {
|
||||
|
||||
fieldrule, err := parseFieldRule(msg)
|
||||
if err != nil {
|
||||
log.Error("Invalid field rule: ", err)
|
||||
return nil
|
||||
}
|
||||
return fieldrule
|
||||
}
|
||||
if rawRule.Type == "chinaip" {
|
||||
chinaiprule, err := parseChinaIPRule(msg)
|
||||
if err != nil {
|
||||
log.Error("Router: Invalid chinaip rule: ", err)
|
||||
return nil
|
||||
}
|
||||
return chinaiprule
|
||||
}
|
||||
if rawRule.Type == "chinasites" {
|
||||
chinasitesrule, err := parseChinaSitesRule(msg)
|
||||
if err != nil {
|
||||
log.Error("Invalid chinasites rule: ", err)
|
||||
return nil
|
||||
}
|
||||
return chinasitesrule
|
||||
}
|
||||
log.Error("Unknown router rule type: ", rawRule.Type)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
router.RegisterRouterConfig("rules", func(data []byte) (interface{}, error) {
|
||||
type JsonConfig struct {
|
||||
RuleList []json.RawMessage `json:"rules"`
|
||||
DomainStrategy string `json:"domainStrategy"`
|
||||
}
|
||||
jsonConfig := new(JsonConfig)
|
||||
if err := json.Unmarshal(data, jsonConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config := &RouterRuleConfig{
|
||||
Rules: make([]*Rule, len(jsonConfig.RuleList)),
|
||||
DomainStrategy: DomainAsIs,
|
||||
}
|
||||
domainStrategy := strings.ToLower(jsonConfig.DomainStrategy)
|
||||
if domainStrategy == "alwaysip" {
|
||||
config.DomainStrategy = AlwaysUseIP
|
||||
} else if domainStrategy == "ipifnonmatch" {
|
||||
config.DomainStrategy = UseIPIfNonMatch
|
||||
}
|
||||
for idx, rawRule := range jsonConfig.RuleList {
|
||||
rule := ParseRule(rawRule)
|
||||
config.Rules[idx] = rule
|
||||
}
|
||||
return config, nil
|
||||
})
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package rules_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/app/router/rules"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestDomainRule(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rule := ParseRule([]byte(`{
|
||||
"type": "field",
|
||||
"domain": [
|
||||
"ooxx.com",
|
||||
"oxox.com",
|
||||
"regexp:\\.cn$"
|
||||
],
|
||||
"network": "tcp",
|
||||
"outboundTag": "direct"
|
||||
}`))
|
||||
assert.Pointer(rule).IsNotNil()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.DomainAddress("www.ooxx.com"), 80))).IsTrue()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.DomainAddress("www.aabb.com"), 80))).IsFalse()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), 80))).IsFalse()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.DomainAddress("www.12306.cn"), 80))).IsTrue()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.DomainAddress("www.acn.com"), 80))).IsFalse()
|
||||
}
|
||||
|
||||
func TestIPRule(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rule := ParseRule([]byte(`{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"10.0.0.0/8",
|
||||
"192.0.0.0/24"
|
||||
],
|
||||
"network": "tcp",
|
||||
"outboundTag": "direct"
|
||||
}`))
|
||||
assert.Pointer(rule).IsNotNil()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.DomainAddress("www.ooxx.com"), 80))).IsFalse()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}), 80))).IsTrue()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{127, 0, 0, 1}), 80))).IsFalse()
|
||||
assert.Bool(rule.Apply(v2net.TCPDestination(v2net.IPAddress([]byte{192, 0, 0, 1}), 80))).IsTrue()
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/app/dns"
|
||||
"github.com/v2ray/v2ray-core/app/router"
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidRule = errors.New("Invalid Rule")
|
||||
ErrNoRuleApplicable = errors.New("No rule applicable")
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
config *RouterRuleConfig
|
||||
cache *RoutingTable
|
||||
dnsServer dns.Server
|
||||
}
|
||||
|
||||
func NewRouter(config *RouterRuleConfig, space app.Space) *Router {
|
||||
r := &Router{
|
||||
config: config,
|
||||
cache: NewRoutingTable(),
|
||||
}
|
||||
space.InitializeApplication(func() error {
|
||||
if !space.HasApp(dns.APP_ID) {
|
||||
log.Error("DNS: Router is not found in the space.")
|
||||
return app.ErrMissingApplication
|
||||
}
|
||||
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
|
||||
return nil
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func (this *Router) Release() {
|
||||
|
||||
}
|
||||
|
||||
// @Private
|
||||
func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
|
||||
ips := this.dnsServer.Get(dest.Address().Domain())
|
||||
if len(ips) == 0 {
|
||||
return nil
|
||||
}
|
||||
dests := make([]v2net.Destination, len(ips))
|
||||
for idx, ip := range ips {
|
||||
if dest.IsTCP() {
|
||||
dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port())
|
||||
} else {
|
||||
dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port())
|
||||
}
|
||||
}
|
||||
return dests
|
||||
}
|
||||
|
||||
func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) {
|
||||
for _, rule := range this.config.Rules {
|
||||
if rule.Apply(dest) {
|
||||
return rule.Tag, nil
|
||||
}
|
||||
}
|
||||
if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().Family().IsDomain() {
|
||||
log.Info("Router: Looking up IP for ", dest)
|
||||
ipDests := this.ResolveIP(dest)
|
||||
if ipDests != nil {
|
||||
for _, ipDest := range ipDests {
|
||||
log.Info("Router: Trying IP ", ipDest)
|
||||
for _, rule := range this.config.Rules {
|
||||
if rule.Apply(ipDest) {
|
||||
return rule.Tag, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", ErrNoRuleApplicable
|
||||
}
|
||||
|
||||
func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
|
||||
destStr := dest.String()
|
||||
found, tag, err := this.cache.Get(destStr)
|
||||
if !found {
|
||||
tag, err := this.takeDetourWithoutCache(dest)
|
||||
this.cache.Set(destStr, tag, err)
|
||||
return tag, err
|
||||
}
|
||||
return tag, err
|
||||
}
|
||||
|
||||
type RouterFactory struct {
|
||||
}
|
||||
|
||||
func (this *RouterFactory) Create(rawConfig interface{}, space app.Space) (router.Router, error) {
|
||||
return NewRouter(rawConfig.(*RouterRuleConfig), space), nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
router.RegisterRouter("rules", &RouterFactory{})
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package rules_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/v2ray/v2ray-core/app"
|
||||
"github.com/v2ray/v2ray-core/app/dispatcher"
|
||||
dispatchers "github.com/v2ray/v2ray-core/app/dispatcher/impl"
|
||||
"github.com/v2ray/v2ray-core/app/dns"
|
||||
"github.com/v2ray/v2ray-core/app/proxyman"
|
||||
"github.com/v2ray/v2ray-core/app/router"
|
||||
. "github.com/v2ray/v2ray-core/app/router/rules"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestSimpleRouter(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
config := &RouterRuleConfig{
|
||||
Rules: []*Rule{
|
||||
{
|
||||
Tag: "test",
|
||||
Condition: NewNetworkMatcher(v2net.Network("tcp").AsList()),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
space := app.NewSpace()
|
||||
space.BindApp(dns.APP_ID, dns.NewCacheServer(space, &dns.Config{}))
|
||||
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
|
||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, proxyman.NewDefaultOutboundHandlerManager())
|
||||
r := NewRouter(config, space)
|
||||
space.BindApp(router.APP_ID, r)
|
||||
assert.Error(space.Initialize()).IsNil()
|
||||
|
||||
tag, err := r.TakeDetour(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80))
|
||||
assert.Error(err).IsNil()
|
||||
assert.String(tag).Equals("test")
|
||||
}
|
||||
29
app/space.go
29
app/space.go
@@ -3,7 +3,7 @@ package app
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common"
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -26,6 +26,19 @@ type Application interface {
|
||||
}
|
||||
|
||||
type ApplicationInitializer func() error
|
||||
type ApplicationFactory interface {
|
||||
Create(space Space, config interface{}) (Application, error)
|
||||
AppId() ID
|
||||
}
|
||||
|
||||
var (
|
||||
applicationFactoryCache = make(map[string]ApplicationFactory)
|
||||
)
|
||||
|
||||
func RegisterApplicationFactory(name string, factory ApplicationFactory) error {
|
||||
applicationFactoryCache[name] = factory
|
||||
return nil
|
||||
}
|
||||
|
||||
// A Space contains all apps that may be available in a V2Ray runtime.
|
||||
// Caller must check the availability of an app by calling HasXXX before getting its instance.
|
||||
@@ -36,6 +49,7 @@ type Space interface {
|
||||
HasApp(ID) bool
|
||||
GetApp(ID) Application
|
||||
BindApp(ID, Application)
|
||||
BindFromConfig(name string, config interface{}) error
|
||||
}
|
||||
|
||||
type spaceImpl struct {
|
||||
@@ -80,3 +94,16 @@ func (this *spaceImpl) GetApp(id ID) Application {
|
||||
func (this *spaceImpl) BindApp(id ID, application Application) {
|
||||
this.cache[id] = application
|
||||
}
|
||||
|
||||
func (this *spaceImpl) BindFromConfig(name string, config interface{}) error {
|
||||
factory, found := applicationFactoryCache[name]
|
||||
if !found {
|
||||
return errors.New("Space: app not registered: " + name)
|
||||
}
|
||||
app, err := factory.Create(this, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.BindApp(factory.AppId(), app)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/serial"
|
||||
"v2ray.com/core/common/serial"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -52,6 +52,7 @@ func (b *Buffer) Clear() *Buffer {
|
||||
return b
|
||||
}
|
||||
|
||||
// Reset resets this Buffer into its original state.
|
||||
func (b *Buffer) Reset() *Buffer {
|
||||
b.offset = defaultOffset
|
||||
b.Value = b.head
|
||||
@@ -199,11 +200,6 @@ func (b *Buffer) String() string {
|
||||
return string(b.Value)
|
||||
}
|
||||
|
||||
// NewSmallBuffer creates a Buffer with 1K bytes of arbitrary content.
|
||||
func NewSmallBuffer() *Buffer {
|
||||
return smallPool.Allocate()
|
||||
}
|
||||
|
||||
// NewBuffer creates a Buffer with 8K bytes of arbitrary content.
|
||||
func NewBuffer() *Buffer {
|
||||
return mediumPool.Allocate()
|
||||
@@ -215,10 +211,6 @@ func NewLargeBuffer() *Buffer {
|
||||
}
|
||||
|
||||
func NewBufferWithSize(size int) *Buffer {
|
||||
if size <= SmallBufferSize {
|
||||
return NewSmallBuffer()
|
||||
}
|
||||
|
||||
if size <= BufferSize {
|
||||
return NewBuffer()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package alloc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -14,14 +16,14 @@ type BufferPool struct {
|
||||
allocator *sync.Pool
|
||||
}
|
||||
|
||||
func NewBufferPool(bufferSize, poolSize int) *BufferPool {
|
||||
func NewBufferPool(bufferSize, poolSize uint32) *BufferPool {
|
||||
pool := &BufferPool{
|
||||
chain: make(chan []byte, poolSize),
|
||||
allocator: &sync.Pool{
|
||||
New: func() interface{} { return make([]byte, bufferSize) },
|
||||
},
|
||||
}
|
||||
for i := 0; i < poolSize; i++ {
|
||||
for i := uint32(0); i < poolSize; i++ {
|
||||
pool.chain <- make([]byte, bufferSize)
|
||||
}
|
||||
return pool
|
||||
@@ -50,11 +52,30 @@ func (p *BufferPool) Free(buffer *Buffer) {
|
||||
}
|
||||
|
||||
const (
|
||||
SmallBufferSize = 1600 - defaultOffset
|
||||
BufferSize = 8*1024 - defaultOffset
|
||||
LargeBufferSize = 64*1024 - defaultOffset
|
||||
mediumBufferByteSize = 8 * 1024
|
||||
BufferSize = mediumBufferByteSize - defaultOffset
|
||||
|
||||
largeBufferByteSize = 64 * 1024
|
||||
LargeBufferSize = largeBufferByteSize - defaultOffset
|
||||
|
||||
PoolSizeEnvKey = "v2ray.buffer.size"
|
||||
)
|
||||
|
||||
var smallPool = NewBufferPool(1600, 256)
|
||||
var mediumPool = NewBufferPool(8*1024, 1024)
|
||||
var largePool = NewBufferPool(64*1024, 32)
|
||||
var (
|
||||
mediumPool *BufferPool
|
||||
largePool *BufferPool
|
||||
)
|
||||
|
||||
func init() {
|
||||
var size uint32 = 20
|
||||
sizeStr := os.Getenv(PoolSizeEnvKey)
|
||||
if len(sizeStr) > 0 {
|
||||
customSize, err := strconv.ParseUint(sizeStr, 10, 32)
|
||||
if err == nil {
|
||||
size = uint32(customSize)
|
||||
}
|
||||
}
|
||||
totalByteSize := size * 1024 * 1024
|
||||
mediumPool = NewBufferPool(mediumBufferByteSize, totalByteSize/4*3/mediumBufferByteSize)
|
||||
largePool = NewBufferPool(largeBufferByteSize, totalByteSize/4/largeBufferByteSize)
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package alloc_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/alloc"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
. "v2ray.com/core/common/alloc"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestBufferClear(t *testing.T) {
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package collect
|
||||
|
||||
type StringList []string
|
||||
|
||||
func NewStringList(raw []string) *StringList {
|
||||
list := StringList(raw)
|
||||
return &list
|
||||
}
|
||||
|
||||
func (this *StringList) Len() int {
|
||||
return len(*this)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package collect
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (this *StringList) UnmarshalJSON(data []byte) error {
|
||||
var strarray []string
|
||||
if err := json.Unmarshal(data, &strarray); err == nil {
|
||||
*this = *NewStringList(strarray)
|
||||
return nil
|
||||
}
|
||||
|
||||
var rawstr string
|
||||
if err := json.Unmarshal(data, &rawstr); err == nil {
|
||||
strlist := strings.Split(rawstr, ",")
|
||||
*this = *NewStringList(strlist)
|
||||
return nil
|
||||
}
|
||||
return errors.New("Unknown format of a string list: " + string(data))
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package collect_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/collect"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestStringListUnmarshalError(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rawJson := `1234`
|
||||
list := new(StringList)
|
||||
err := json.Unmarshal([]byte(rawJson), list)
|
||||
assert.Error(err).IsNotNil()
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
var (
|
||||
ErrObjectReleased = errors.New("Object already released.")
|
||||
ErrBadConfiguration = errors.New("Bad configuration.")
|
||||
ErrObjectNotFound = errors.New("Object not found.")
|
||||
ErrDuplicatedName = errors.New("Duplicated name.")
|
||||
)
|
||||
|
||||
// Releasable interface is for those types that can release its members.
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"crypto/cipher"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/crypto"
|
||||
. "v2ray.com/core/common/crypto"
|
||||
)
|
||||
|
||||
const benchSize = 1024 * 1024
|
||||
@@ -13,6 +13,7 @@ func benchmarkStream(b *testing.B, c cipher.Stream) {
|
||||
b.SetBytes(benchSize)
|
||||
input := make([]byte, benchSize)
|
||||
output := make([]byte, benchSize)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.XORKeyStream(output, input)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package crypto
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/crypto/internal"
|
||||
"v2ray.com/core/common/crypto/internal"
|
||||
)
|
||||
|
||||
// NewChaCha20Stream creates a new Chacha20 encryption/descryption stream based on give key and IV.
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/crypto"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
. "v2ray.com/core/common/crypto"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func mustDecodeHex(s string) []byte {
|
||||
|
||||
3
common/crypto/crypto.go
Normal file
3
common/crypto/crypto.go
Normal file
@@ -0,0 +1,3 @@
|
||||
// Provides common crypto libraries for V2Ray.
|
||||
|
||||
package crypto
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"crypto/cipher"
|
||||
"io"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common"
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
type CryptionReader struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"v2ray.com/core/common/alloc"
|
||||
)
|
||||
|
||||
type BufferedReader struct {
|
||||
|
||||
@@ -3,9 +3,9 @@ package io_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
. "github.com/v2ray/v2ray-core/common/io"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
"v2ray.com/core/common/alloc"
|
||||
. "v2ray.com/core/common/io"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestBufferedReader(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"v2ray.com/core/common/alloc"
|
||||
)
|
||||
|
||||
type BufferedWriter struct {
|
||||
|
||||
@@ -3,9 +3,9 @@ package io_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
. "github.com/v2ray/v2ray-core/common/io"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
"v2ray.com/core/common/alloc"
|
||||
. "v2ray.com/core/common/io"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestBufferedWriter(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"v2ray.com/core/common/alloc"
|
||||
)
|
||||
|
||||
type ChainWriter struct {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"v2ray.com/core/common/alloc"
|
||||
)
|
||||
|
||||
type ChanReader struct {
|
||||
@@ -15,14 +15,12 @@ type ChanReader struct {
|
||||
}
|
||||
|
||||
func NewChanReader(stream Reader) *ChanReader {
|
||||
this := &ChanReader{
|
||||
return &ChanReader{
|
||||
stream: stream,
|
||||
}
|
||||
this.Fill()
|
||||
return this
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Visible for testing.
|
||||
func (this *ChanReader) Fill() {
|
||||
b, err := this.stream.Read()
|
||||
this.current = b
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package io // import "github.com/v2ray/v2ray-core/common/io"
|
||||
package io
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common"
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/alloc"
|
||||
)
|
||||
|
||||
// Reader extends io.Reader with alloc.Buffer.
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
. "github.com/v2ray/v2ray-core/common/io"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
"v2ray.com/core/common/alloc"
|
||||
. "v2ray.com/core/common/io"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestAdaptiveReader(t *testing.T) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
"v2ray.com/core/common/log"
|
||||
)
|
||||
|
||||
func Pipe(reader Reader, writer Writer) error {
|
||||
|
||||
@@ -3,8 +3,8 @@ package io
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common"
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/alloc"
|
||||
)
|
||||
|
||||
// Writer extends io.Writer with alloc.Buffer.
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
. "github.com/v2ray/v2ray-core/common/io"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
"v2ray.com/core/common/alloc"
|
||||
. "v2ray.com/core/common/io"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestAdaptiveWriter(t *testing.T) {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrConfigIDKeyNotFound = errors.New("Config ID key is not found.")
|
||||
ErrConfigIDExists = errors.New("Config ID already exists.")
|
||||
ErrUnknownConfigID = errors.New("Unknown config ID.")
|
||||
)
|
||||
|
||||
type ConfigCreator func() interface{}
|
||||
|
||||
type ConfigLoader interface {
|
||||
RegisterCreator(string, ConfigCreator) error
|
||||
CreateConfig(string) (interface{}, error)
|
||||
Load([]byte) (interface{}, string, error)
|
||||
LoadWithID([]byte, string) (interface{}, error)
|
||||
}
|
||||
|
||||
type BaseConfigLoader struct {
|
||||
creators map[string]ConfigCreator
|
||||
}
|
||||
|
||||
func NewBaseConfigLoader() *BaseConfigLoader {
|
||||
return &BaseConfigLoader{
|
||||
creators: make(map[string]ConfigCreator),
|
||||
}
|
||||
}
|
||||
|
||||
func (this *BaseConfigLoader) RegisterCreator(id string, creator ConfigCreator) error {
|
||||
if _, found := this.creators[id]; found {
|
||||
return ErrConfigIDExists
|
||||
}
|
||||
|
||||
this.creators[id] = creator
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *BaseConfigLoader) CreateConfig(id string) (interface{}, error) {
|
||||
creator, found := this.creators[id]
|
||||
if !found {
|
||||
return nil, ErrUnknownConfigID
|
||||
}
|
||||
return creator(), nil
|
||||
}
|
||||
50
common/loader/type.go
Normal file
50
common/loader/type.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
func NewTypedSettings(message proto.Message) *TypedSettings {
|
||||
if message == nil {
|
||||
return nil
|
||||
}
|
||||
settings, _ := proto.Marshal(message)
|
||||
return &TypedSettings{
|
||||
Type: GetType(message),
|
||||
Settings: settings,
|
||||
}
|
||||
}
|
||||
|
||||
func GetType(message proto.Message) string {
|
||||
return proto.MessageName(message)
|
||||
}
|
||||
|
||||
func GetInstance(messageType string) (interface{}, error) {
|
||||
mType := proto.MessageType(messageType).Elem()
|
||||
if mType == nil {
|
||||
return nil, errors.New("Unknown type: " + messageType)
|
||||
}
|
||||
return reflect.New(mType).Interface(), nil
|
||||
}
|
||||
|
||||
func (this *TypedSettings) Load(message proto.Message) error {
|
||||
targetType := GetType(message)
|
||||
if targetType != this.Type {
|
||||
return errors.New("Have type " + this.Type + ", but retrieved for " + targetType)
|
||||
}
|
||||
return proto.Unmarshal(this.Settings, message)
|
||||
}
|
||||
|
||||
func (this *TypedSettings) GetInstance() (interface{}, error) {
|
||||
instance, err := GetInstance(this.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := proto.Unmarshal(this.Settings, instance.(proto.Message)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return instance, nil
|
||||
}
|
||||
62
common/loader/type.pb.go
Normal file
62
common/loader/type.pb.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/common/loader/type.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package loader is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
v2ray.com/core/common/loader/type.proto
|
||||
|
||||
It has these top-level messages:
|
||||
TypedSettings
|
||||
*/
|
||||
package loader
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Serialized proto message along with its type name.
|
||||
type TypedSettings struct {
|
||||
// The name of the message type, retrieved from protobuf API.
|
||||
Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
|
||||
// Serialized proto message.
|
||||
Settings []byte `protobuf:"bytes,2,opt,name=settings,proto3" json:"settings,omitempty"`
|
||||
}
|
||||
|
||||
func (m *TypedSettings) Reset() { *m = TypedSettings{} }
|
||||
func (m *TypedSettings) String() string { return proto.CompactTextString(m) }
|
||||
func (*TypedSettings) ProtoMessage() {}
|
||||
func (*TypedSettings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*TypedSettings)(nil), "v2ray.core.common.loader.TypedSettings")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/common/loader/type.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 151 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x33, 0x2a, 0x4a,
|
||||
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcd, 0xcd,
|
||||
0xcf, 0xd3, 0xcf, 0xc9, 0x4f, 0x4c, 0x49, 0x2d, 0xd2, 0x2f, 0xa9, 0x2c, 0x48, 0xd5, 0x2b, 0x28,
|
||||
0xca, 0x2f, 0xc9, 0x17, 0x92, 0x80, 0x29, 0x2c, 0x4a, 0xd5, 0x83, 0x28, 0xd2, 0x83, 0x28, 0x52,
|
||||
0xb2, 0xe7, 0xe2, 0x0d, 0xa9, 0x2c, 0x48, 0x4d, 0x09, 0x4e, 0x2d, 0x29, 0xc9, 0xcc, 0x4b, 0x2f,
|
||||
0x16, 0x12, 0xe2, 0x62, 0x01, 0x69, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x85,
|
||||
0xa4, 0xb8, 0x38, 0x8a, 0xa1, 0xf2, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x70, 0xbe, 0x93,
|
||||
0x21, 0x97, 0x4c, 0x72, 0x7e, 0xae, 0x1e, 0x2e, 0x0b, 0x9c, 0x38, 0x41, 0xc6, 0x07, 0x80, 0x5c,
|
||||
0x11, 0xc5, 0x06, 0x11, 0x4a, 0x62, 0x03, 0x3b, 0xca, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x24,
|
||||
0xa2, 0x4d, 0x76, 0xbf, 0x00, 0x00, 0x00,
|
||||
}
|
||||
14
common/loader/type.proto
Normal file
14
common/loader/type.proto
Normal file
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.loader;
|
||||
option go_package = "loader";
|
||||
option java_package = "com.v2ray.core.common.loader";
|
||||
option java_outer_classname = "TypeProto";
|
||||
|
||||
// Serialized proto message along with its type name.
|
||||
message TypedSettings {
|
||||
// The name of the message type, retrieved from protobuf API.
|
||||
string type = 1;
|
||||
// Serialized proto message.
|
||||
bytes settings = 2;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/common/log/internal"
|
||||
"v2ray.com/core/common/log/internal"
|
||||
)
|
||||
|
||||
// AccessStatus is the status of an access request from clients.
|
||||
|
||||
25
common/log/config.go
Normal file
25
common/log/config.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package log
|
||||
|
||||
func (this *Config) Apply() error {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
if this.AccessLogType == LogType_File {
|
||||
if err := InitAccessLogger(this.AccessLogPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if this.ErrorLogType == LogType_None {
|
||||
SetLogLevel(LogLevel_Disabled)
|
||||
} else {
|
||||
if this.ErrorLogType == LogType_File {
|
||||
if err := InitErrorLogger(this.ErrorLogPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
SetLogLevel(this.ErrorLogLevel)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
132
common/log/config.pb.go
Normal file
132
common/log/config.pb.go
Normal file
@@ -0,0 +1,132 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/common/log/config.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package log is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
v2ray.com/core/common/log/config.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Config
|
||||
*/
|
||||
package log
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type LogType int32
|
||||
|
||||
const (
|
||||
LogType_None LogType = 0
|
||||
LogType_Console LogType = 1
|
||||
LogType_File LogType = 2
|
||||
LogType_Event LogType = 3
|
||||
)
|
||||
|
||||
var LogType_name = map[int32]string{
|
||||
0: "None",
|
||||
1: "Console",
|
||||
2: "File",
|
||||
3: "Event",
|
||||
}
|
||||
var LogType_value = map[string]int32{
|
||||
"None": 0,
|
||||
"Console": 1,
|
||||
"File": 2,
|
||||
"Event": 3,
|
||||
}
|
||||
|
||||
func (x LogType) String() string {
|
||||
return proto.EnumName(LogType_name, int32(x))
|
||||
}
|
||||
func (LogType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
type LogLevel int32
|
||||
|
||||
const (
|
||||
LogLevel_Disabled LogLevel = 0
|
||||
LogLevel_Error LogLevel = 1
|
||||
LogLevel_Warning LogLevel = 2
|
||||
LogLevel_Info LogLevel = 3
|
||||
LogLevel_Debug LogLevel = 4
|
||||
)
|
||||
|
||||
var LogLevel_name = map[int32]string{
|
||||
0: "Disabled",
|
||||
1: "Error",
|
||||
2: "Warning",
|
||||
3: "Info",
|
||||
4: "Debug",
|
||||
}
|
||||
var LogLevel_value = map[string]int32{
|
||||
"Disabled": 0,
|
||||
"Error": 1,
|
||||
"Warning": 2,
|
||||
"Info": 3,
|
||||
"Debug": 4,
|
||||
}
|
||||
|
||||
func (x LogLevel) String() string {
|
||||
return proto.EnumName(LogLevel_name, int32(x))
|
||||
}
|
||||
func (LogLevel) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
type Config struct {
|
||||
ErrorLogType LogType `protobuf:"varint,1,opt,name=error_log_type,json=errorLogType,enum=v2ray.core.common.log.LogType" json:"error_log_type,omitempty"`
|
||||
ErrorLogLevel LogLevel `protobuf:"varint,2,opt,name=error_log_level,json=errorLogLevel,enum=v2ray.core.common.log.LogLevel" json:"error_log_level,omitempty"`
|
||||
ErrorLogPath string `protobuf:"bytes,3,opt,name=error_log_path,json=errorLogPath" json:"error_log_path,omitempty"`
|
||||
AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,enum=v2ray.core.common.log.LogType" json:"access_log_type,omitempty"`
|
||||
AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath" json:"access_log_path,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Config) Reset() { *m = Config{} }
|
||||
func (m *Config) String() string { return proto.CompactTextString(m) }
|
||||
func (*Config) ProtoMessage() {}
|
||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Config)(nil), "v2ray.core.common.log.Config")
|
||||
proto.RegisterEnum("v2ray.core.common.log.LogType", LogType_name, LogType_value)
|
||||
proto.RegisterEnum("v2ray.core.common.log.LogLevel", LogLevel_name, LogLevel_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/common/log/config.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 322 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x91, 0x6d, 0x4b, 0xf3, 0x30,
|
||||
0x14, 0x86, 0xd7, 0x76, 0xaf, 0xd9, 0x5b, 0x08, 0x3c, 0xb0, 0xe7, 0x8b, 0x0e, 0x91, 0x31, 0x06,
|
||||
0xb6, 0x30, 0xf1, 0x0f, 0xec, 0x4d, 0x84, 0x21, 0x63, 0x08, 0x82, 0x5f, 0x46, 0x17, 0xcf, 0xb2,
|
||||
0x42, 0x9a, 0x53, 0xd2, 0x3a, 0xd8, 0x8f, 0xf2, 0x3f, 0x4a, 0x32, 0x6b, 0x15, 0x26, 0xf8, 0x31,
|
||||
0xe1, 0x3a, 0xd7, 0x7d, 0x1f, 0x0e, 0x19, 0x1c, 0xc6, 0x3a, 0x3c, 0xfa, 0x1c, 0xe3, 0x80, 0xa3,
|
||||
0x86, 0x80, 0x63, 0x1c, 0xa3, 0x0a, 0x24, 0x8a, 0x80, 0xa3, 0xda, 0x45, 0xc2, 0x4f, 0x34, 0x66,
|
||||
0xc8, 0xfe, 0xe5, 0x9c, 0x06, 0xff, 0xc4, 0xf8, 0x12, 0xc5, 0xd5, 0xbb, 0x4b, 0xaa, 0x53, 0xcb,
|
||||
0xb1, 0x19, 0xe9, 0x80, 0xd6, 0xa8, 0x37, 0x12, 0xc5, 0x26, 0x3b, 0x26, 0xd0, 0x73, 0xfa, 0xce,
|
||||
0xb0, 0x33, 0xbe, 0xf0, 0xcf, 0x8e, 0xfa, 0x4b, 0x14, 0x4f, 0xc7, 0x04, 0xd6, 0x2d, 0x3b, 0xf5,
|
||||
0xf9, 0x62, 0xf7, 0xa4, 0x5b, 0x58, 0x24, 0x1c, 0x40, 0xf6, 0x5c, 0xab, 0xb9, 0xfc, 0x5d, 0xb3,
|
||||
0x34, 0xd8, 0xba, 0x9d, 0x7b, 0xec, 0x93, 0x5d, 0x7f, 0xaf, 0x93, 0x84, 0xd9, 0xbe, 0xe7, 0xf5,
|
||||
0x9d, 0x61, 0xa3, 0x88, 0x5b, 0x85, 0xd9, 0x9e, 0x2d, 0x48, 0x37, 0xe4, 0x1c, 0xd2, 0xb4, 0x68,
|
||||
0x5d, 0xfe, 0x53, 0xeb, 0xf6, 0x69, 0x2c, 0xaf, 0x3d, 0xf8, 0xe1, 0xb1, 0x71, 0x15, 0x1b, 0x57,
|
||||
0x70, 0x26, 0x6f, 0x74, 0x47, 0x6a, 0xf9, 0x48, 0x9d, 0x94, 0x1f, 0x51, 0x01, 0x2d, 0xb1, 0x26,
|
||||
0xa9, 0x4d, 0x51, 0xa5, 0x28, 0x81, 0x3a, 0xe6, 0x7b, 0x11, 0x49, 0xa0, 0x2e, 0x6b, 0x90, 0xca,
|
||||
0xfc, 0x00, 0x2a, 0xa3, 0xde, 0x68, 0x4e, 0xea, 0x5f, 0x8b, 0xb5, 0x48, 0x7d, 0x16, 0xa5, 0xe1,
|
||||
0x56, 0xc2, 0x2b, 0x2d, 0x59, 0xc8, 0x2c, 0x44, 0x1d, 0xa3, 0x79, 0x0e, 0xb5, 0x8a, 0x94, 0xa0,
|
||||
0xae, 0xd1, 0x3c, 0xa8, 0x1d, 0x52, 0xcf, 0x10, 0x33, 0xd8, 0xbe, 0x09, 0x5a, 0x9e, 0xdc, 0x90,
|
||||
0xff, 0x1c, 0xe3, 0xf3, 0x9b, 0x4d, 0x9a, 0xa7, 0x3b, 0xae, 0xcc, 0xb9, 0x5f, 0x3c, 0x89, 0x62,
|
||||
0x5b, 0xb5, 0xa7, 0xbf, 0xfd, 0x08, 0x00, 0x00, 0xff, 0xff, 0x11, 0x55, 0x7e, 0x04, 0x24, 0x02,
|
||||
0x00, 0x00,
|
||||
}
|
||||
30
common/log/config.proto
Normal file
30
common/log/config.proto
Normal file
@@ -0,0 +1,30 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.log;
|
||||
option go_package = "log";
|
||||
option java_package = "com.v2ray.core.common.log";
|
||||
option java_outer_classname = "ConfigProto";
|
||||
|
||||
enum LogType {
|
||||
None = 0;
|
||||
Console = 1;
|
||||
File = 2;
|
||||
Event = 3;
|
||||
}
|
||||
|
||||
enum LogLevel {
|
||||
Disabled = 0;
|
||||
Error = 1;
|
||||
Warning = 2;
|
||||
Info = 3;
|
||||
Debug = 4;
|
||||
}
|
||||
|
||||
message Config {
|
||||
LogType error_log_type = 1;
|
||||
LogLevel error_log_level = 2;
|
||||
string error_log_path = 3;
|
||||
|
||||
LogType access_log_type = 4;
|
||||
string access_log_path = 5;
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common"
|
||||
"github.com/v2ray/v2ray-core/common/serial"
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/serial"
|
||||
)
|
||||
|
||||
func InterfaceToString(value interface{}) string {
|
||||
|
||||
@@ -3,8 +3,8 @@ package internal_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/log/internal"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
. "v2ray.com/core/common/log/internal"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestAccessLog(t *testing.T) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/platform"
|
||||
"github.com/v2ray/v2ray-core/common/signal"
|
||||
"v2ray.com/core/common/platform"
|
||||
"v2ray.com/core/common/signal"
|
||||
)
|
||||
|
||||
type LogWriter interface {
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/common/log/internal"
|
||||
)
|
||||
|
||||
type LogLevel int
|
||||
|
||||
const (
|
||||
DebugLevel = LogLevel(0)
|
||||
InfoLevel = LogLevel(1)
|
||||
WarningLevel = LogLevel(2)
|
||||
ErrorLevel = LogLevel(3)
|
||||
NoneLevel = LogLevel(999)
|
||||
"v2ray.com/core/common/log/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -25,28 +15,24 @@ var (
|
||||
|
||||
func SetLogLevel(level LogLevel) {
|
||||
debugLogger = new(internal.NoOpLogWriter)
|
||||
if level <= DebugLevel {
|
||||
if level >= LogLevel_Debug {
|
||||
debugLogger = streamLoggerInstance
|
||||
}
|
||||
|
||||
infoLogger = new(internal.NoOpLogWriter)
|
||||
if level <= InfoLevel {
|
||||
if level >= LogLevel_Info {
|
||||
infoLogger = streamLoggerInstance
|
||||
}
|
||||
|
||||
warningLogger = new(internal.NoOpLogWriter)
|
||||
if level <= WarningLevel {
|
||||
if level >= LogLevel_Warning {
|
||||
warningLogger = streamLoggerInstance
|
||||
}
|
||||
|
||||
errorLogger = new(internal.NoOpLogWriter)
|
||||
if level <= ErrorLevel {
|
||||
if level >= LogLevel_Error {
|
||||
errorLogger = streamLoggerInstance
|
||||
}
|
||||
|
||||
if level == NoneLevel {
|
||||
accessLoggerInstance = new(internal.NoOpLogWriter)
|
||||
}
|
||||
}
|
||||
|
||||
func InitErrorLogger(file string) error {
|
||||
|
||||
@@ -3,8 +3,8 @@ package net
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
"github.com/v2ray/v2ray-core/common/predicate"
|
||||
"v2ray.com/core/common/log"
|
||||
"v2ray.com/core/common/predicate"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -186,3 +186,16 @@ func (this *domainAddress) Equals(another Address) bool {
|
||||
}
|
||||
return this.Domain() == anotherDomain.Domain()
|
||||
}
|
||||
|
||||
func (this *IPOrDomain) AsAddress() Address {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
switch addr := this.Address.(type) {
|
||||
case *IPOrDomain_Ip:
|
||||
return IPAddress(addr.Ip)
|
||||
case *IPOrDomain_Domain:
|
||||
return DomainAddress(addr.Domain)
|
||||
}
|
||||
panic("Common|Net: Invalid address.")
|
||||
}
|
||||
|
||||
169
common/net/address.pb.go
Normal file
169
common/net/address.pb.go
Normal file
@@ -0,0 +1,169 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/common/net/address.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package net is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
v2ray.com/core/common/net/address.proto
|
||||
v2ray.com/core/common/net/destination.proto
|
||||
v2ray.com/core/common/net/network.proto
|
||||
v2ray.com/core/common/net/port.proto
|
||||
|
||||
It has these top-level messages:
|
||||
IPOrDomain
|
||||
Endpoint
|
||||
NetworkList
|
||||
PortRange
|
||||
*/
|
||||
package net
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type IPOrDomain struct {
|
||||
// Types that are valid to be assigned to Address:
|
||||
// *IPOrDomain_Ip
|
||||
// *IPOrDomain_Domain
|
||||
Address isIPOrDomain_Address `protobuf_oneof:"address"`
|
||||
}
|
||||
|
||||
func (m *IPOrDomain) Reset() { *m = IPOrDomain{} }
|
||||
func (m *IPOrDomain) String() string { return proto.CompactTextString(m) }
|
||||
func (*IPOrDomain) ProtoMessage() {}
|
||||
func (*IPOrDomain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
type isIPOrDomain_Address interface {
|
||||
isIPOrDomain_Address()
|
||||
}
|
||||
|
||||
type IPOrDomain_Ip struct {
|
||||
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3,oneof"`
|
||||
}
|
||||
type IPOrDomain_Domain struct {
|
||||
Domain string `protobuf:"bytes,2,opt,name=domain,oneof"`
|
||||
}
|
||||
|
||||
func (*IPOrDomain_Ip) isIPOrDomain_Address() {}
|
||||
func (*IPOrDomain_Domain) isIPOrDomain_Address() {}
|
||||
|
||||
func (m *IPOrDomain) GetAddress() isIPOrDomain_Address {
|
||||
if m != nil {
|
||||
return m.Address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *IPOrDomain) GetIp() []byte {
|
||||
if x, ok := m.GetAddress().(*IPOrDomain_Ip); ok {
|
||||
return x.Ip
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *IPOrDomain) GetDomain() string {
|
||||
if x, ok := m.GetAddress().(*IPOrDomain_Domain); ok {
|
||||
return x.Domain
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// XXX_OneofFuncs is for the internal use of the proto package.
|
||||
func (*IPOrDomain) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
|
||||
return _IPOrDomain_OneofMarshaler, _IPOrDomain_OneofUnmarshaler, _IPOrDomain_OneofSizer, []interface{}{
|
||||
(*IPOrDomain_Ip)(nil),
|
||||
(*IPOrDomain_Domain)(nil),
|
||||
}
|
||||
}
|
||||
|
||||
func _IPOrDomain_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
|
||||
m := msg.(*IPOrDomain)
|
||||
// address
|
||||
switch x := m.Address.(type) {
|
||||
case *IPOrDomain_Ip:
|
||||
b.EncodeVarint(1<<3 | proto.WireBytes)
|
||||
b.EncodeRawBytes(x.Ip)
|
||||
case *IPOrDomain_Domain:
|
||||
b.EncodeVarint(2<<3 | proto.WireBytes)
|
||||
b.EncodeStringBytes(x.Domain)
|
||||
case nil:
|
||||
default:
|
||||
return fmt.Errorf("IPOrDomain.Address has unexpected type %T", x)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _IPOrDomain_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
|
||||
m := msg.(*IPOrDomain)
|
||||
switch tag {
|
||||
case 1: // address.ip
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeRawBytes(true)
|
||||
m.Address = &IPOrDomain_Ip{x}
|
||||
return true, err
|
||||
case 2: // address.domain
|
||||
if wire != proto.WireBytes {
|
||||
return true, proto.ErrInternalBadWireType
|
||||
}
|
||||
x, err := b.DecodeStringBytes()
|
||||
m.Address = &IPOrDomain_Domain{x}
|
||||
return true, err
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func _IPOrDomain_OneofSizer(msg proto.Message) (n int) {
|
||||
m := msg.(*IPOrDomain)
|
||||
// address
|
||||
switch x := m.Address.(type) {
|
||||
case *IPOrDomain_Ip:
|
||||
n += proto.SizeVarint(1<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(len(x.Ip)))
|
||||
n += len(x.Ip)
|
||||
case *IPOrDomain_Domain:
|
||||
n += proto.SizeVarint(2<<3 | proto.WireBytes)
|
||||
n += proto.SizeVarint(uint64(len(x.Domain)))
|
||||
n += len(x.Domain)
|
||||
case nil:
|
||||
default:
|
||||
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*IPOrDomain)(nil), "v2ray.core.common.net.IPOrDomain")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/common/net/address.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 163 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x33, 0x2a, 0x4a,
|
||||
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcd, 0xcd,
|
||||
0xcf, 0xd3, 0xcf, 0x4b, 0x2d, 0xd1, 0x4f, 0x4c, 0x49, 0x29, 0x4a, 0x2d, 0x2e, 0xd6, 0x2b, 0x28,
|
||||
0xca, 0x2f, 0xc9, 0x17, 0x12, 0x85, 0x29, 0x2c, 0x4a, 0xd5, 0x83, 0x28, 0xd2, 0xcb, 0x4b, 0x2d,
|
||||
0x51, 0x72, 0xe6, 0xe2, 0xf2, 0x0c, 0xf0, 0x2f, 0x72, 0xc9, 0xcf, 0x4d, 0xcc, 0xcc, 0x13, 0x12,
|
||||
0xe0, 0x62, 0xca, 0x2c, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0xf1, 0x60, 0x08, 0x62, 0xca, 0x2c,
|
||||
0x10, 0x92, 0xe0, 0x62, 0x4b, 0x01, 0xcb, 0x49, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x7a, 0x30, 0x04,
|
||||
0x41, 0xf9, 0x4e, 0x9c, 0x5c, 0xec, 0x50, 0x1b, 0x9c, 0xf4, 0xb8, 0x24, 0x93, 0xf3, 0x73, 0xf5,
|
||||
0xb0, 0xda, 0xe0, 0xc4, 0xe3, 0x08, 0x51, 0x15, 0x00, 0x72, 0x46, 0x14, 0x73, 0x5e, 0x6a, 0x49,
|
||||
0x12, 0x1b, 0xd8, 0x49, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x40, 0xbb, 0x8c, 0xbd,
|
||||
0x00, 0x00, 0x00,
|
||||
}
|
||||
16
common/net/address.proto
Normal file
16
common/net/address.proto
Normal file
@@ -0,0 +1,16 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.net;
|
||||
option go_package = "net";
|
||||
option java_package = "com.v2ray.core.common.net";
|
||||
option java_outer_classname = "AddressProto";
|
||||
|
||||
message IPOrDomain {
|
||||
oneof address {
|
||||
// IP address. Must by either 4 or 16 bytes.
|
||||
bytes ip = 1;
|
||||
|
||||
// Domain address.
|
||||
string domain = 2;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type AddressJson struct {
|
||||
Address Address
|
||||
}
|
||||
|
||||
func (this *AddressJson) UnmarshalJSON(data []byte) error {
|
||||
var rawStr string
|
||||
if err := json.Unmarshal(data, &rawStr); err != nil {
|
||||
return err
|
||||
}
|
||||
this.Address = ParseAddress(rawStr)
|
||||
return nil
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package net_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestIPParsing(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rawJson := "\"8.8.8.8\""
|
||||
var address AddressJson
|
||||
err := json.Unmarshal([]byte(rawJson), &address)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Bool(address.Address.Family().Either(AddressFamilyIPv4)).IsTrue()
|
||||
assert.Bool(address.Address.Family().Either(AddressFamilyDomain)).IsFalse()
|
||||
assert.Bool(address.Address.IP().Equal(net.ParseIP("8.8.8.8"))).IsTrue()
|
||||
}
|
||||
|
||||
func TestDomainParsing(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rawJson := "\"v2ray.com\""
|
||||
var address AddressJson
|
||||
err := json.Unmarshal([]byte(rawJson), &address)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Bool(address.Address.Family().Either(AddressFamilyIPv4)).IsFalse()
|
||||
assert.Bool(address.Address.Family().Either(AddressFamilyDomain)).IsTrue()
|
||||
assert.String(address.Address.Domain()).Equals("v2ray.com")
|
||||
}
|
||||
|
||||
func TestInvalidAddressJson(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rawJson := "1234"
|
||||
var address AddressJson
|
||||
err := json.Unmarshal([]byte(rawJson), &address)
|
||||
assert.Error(err).IsNotNil()
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestIPv4Address(t *testing.T) {
|
||||
|
||||
@@ -5,16 +5,10 @@ import (
|
||||
)
|
||||
|
||||
// Destination represents a network destination including address and protocol (tcp / udp).
|
||||
type Destination interface {
|
||||
Network() Network // Protocol of communication (tcp / udp)
|
||||
Address() Address // Address of destination
|
||||
Port() Port
|
||||
String() string // String representation of the destination
|
||||
NetAddr() string
|
||||
Equals(Destination) bool
|
||||
|
||||
IsTCP() bool // True if destination is reachable via TCP
|
||||
IsUDP() bool // True if destination is reachable via UDP
|
||||
type Destination struct {
|
||||
Network Network
|
||||
Address Address
|
||||
Port Port
|
||||
}
|
||||
|
||||
func DestinationFromAddr(addr net.Addr) Destination {
|
||||
@@ -30,102 +24,38 @@ func DestinationFromAddr(addr net.Addr) Destination {
|
||||
|
||||
// TCPDestination creates a TCP destination with given address
|
||||
func TCPDestination(address Address, port Port) Destination {
|
||||
return &tcpDestination{address: address, port: port}
|
||||
return Destination{
|
||||
Network: Network_TCP,
|
||||
Address: address,
|
||||
Port: port,
|
||||
}
|
||||
}
|
||||
|
||||
// UDPDestination creates a UDP destination with given address
|
||||
func UDPDestination(address Address, port Port) Destination {
|
||||
return &udpDestination{address: address, port: port}
|
||||
}
|
||||
|
||||
type tcpDestination struct {
|
||||
address Address
|
||||
port Port
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) Network() Network {
|
||||
return TCPNetwork
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) Address() Address {
|
||||
return dest.address
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) NetAddr() string {
|
||||
return dest.address.String() + ":" + dest.port.String()
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) String() string {
|
||||
return "tcp:" + dest.NetAddr()
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) IsTCP() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) IsUDP() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) Port() Port {
|
||||
return dest.port
|
||||
}
|
||||
|
||||
func (dest *tcpDestination) Equals(another Destination) bool {
|
||||
if dest == nil && another == nil {
|
||||
return true
|
||||
return Destination{
|
||||
Network: Network_UDP,
|
||||
Address: address,
|
||||
Port: port,
|
||||
}
|
||||
if dest == nil || another == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
func (this Destination) NetAddr() string {
|
||||
return this.Address.String() + ":" + this.Port.String()
|
||||
}
|
||||
|
||||
func (this Destination) String() string {
|
||||
return this.Network.UrlPrefix() + ":" + this.NetAddr()
|
||||
}
|
||||
|
||||
func (this Destination) Equals(another Destination) bool {
|
||||
return this.Network == another.Network && this.Port == another.Port && this.Address.Equals(another.Address)
|
||||
}
|
||||
|
||||
func (this *Endpoint) AsDestination() Destination {
|
||||
return Destination{
|
||||
Network: this.Network,
|
||||
Address: this.Address.AsAddress(),
|
||||
Port: Port(this.Port),
|
||||
}
|
||||
if !another.IsTCP() {
|
||||
return false
|
||||
}
|
||||
return dest.Port() == another.Port() && dest.Address().Equals(another.Address())
|
||||
}
|
||||
|
||||
type udpDestination struct {
|
||||
address Address
|
||||
port Port
|
||||
}
|
||||
|
||||
func (dest *udpDestination) Network() Network {
|
||||
return UDPNetwork
|
||||
}
|
||||
|
||||
func (dest *udpDestination) Address() Address {
|
||||
return dest.address
|
||||
}
|
||||
|
||||
func (dest *udpDestination) NetAddr() string {
|
||||
return dest.address.String() + ":" + dest.port.String()
|
||||
}
|
||||
|
||||
func (dest *udpDestination) String() string {
|
||||
return "udp:" + dest.NetAddr()
|
||||
}
|
||||
|
||||
func (dest *udpDestination) IsTCP() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dest *udpDestination) IsUDP() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (dest *udpDestination) Port() Port {
|
||||
return dest.port
|
||||
}
|
||||
|
||||
func (dest *udpDestination) Equals(another Destination) bool {
|
||||
if dest == nil && another == nil {
|
||||
return true
|
||||
}
|
||||
if dest == nil || another == nil {
|
||||
return false
|
||||
}
|
||||
if !another.IsUDP() {
|
||||
return false
|
||||
}
|
||||
return dest.Port() == another.Port() && dest.Address().Equals(another.Address())
|
||||
}
|
||||
|
||||
56
common/net/destination.pb.go
Normal file
56
common/net/destination.pb.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/common/net/destination.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package net
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type Endpoint struct {
|
||||
Network Network `protobuf:"varint,1,opt,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
|
||||
Address *IPOrDomain `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
|
||||
Port uint32 `protobuf:"varint,3,opt,name=port" json:"port,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Endpoint) Reset() { *m = Endpoint{} }
|
||||
func (m *Endpoint) String() string { return proto.CompactTextString(m) }
|
||||
func (*Endpoint) ProtoMessage() {}
|
||||
func (*Endpoint) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
|
||||
|
||||
func (m *Endpoint) GetAddress() *IPOrDomain {
|
||||
if m != nil {
|
||||
return m.Address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Endpoint)(nil), "v2ray.core.common.net.Endpoint")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/common/net/destination.proto", fileDescriptor1) }
|
||||
|
||||
var fileDescriptor1 = []byte{
|
||||
// 219 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x90, 0x31, 0x4b, 0x04, 0x31,
|
||||
0x10, 0x46, 0x89, 0x27, 0x9e, 0x44, 0x14, 0x09, 0x08, 0xab, 0x85, 0xac, 0x36, 0x2e, 0x08, 0x09,
|
||||
0xc4, 0x46, 0xb0, 0x3b, 0xce, 0xc2, 0x46, 0x8f, 0x2d, 0xed, 0x62, 0x32, 0x45, 0x90, 0xcc, 0x2c,
|
||||
0xb3, 0x83, 0xe2, 0x0f, 0xf1, 0xff, 0x8a, 0x97, 0x5b, 0x6c, 0xee, 0xec, 0x52, 0xbc, 0xf7, 0xc8,
|
||||
0x37, 0xfa, 0xf6, 0xc3, 0x73, 0xf8, 0xb2, 0x91, 0x8a, 0x8b, 0xc4, 0xe0, 0x22, 0x95, 0x42, 0xe8,
|
||||
0x10, 0xc4, 0x25, 0x18, 0x25, 0x63, 0x90, 0x4c, 0x68, 0x07, 0x26, 0x21, 0x73, 0x36, 0xc1, 0x0c,
|
||||
0xb6, 0x82, 0x16, 0x41, 0x2e, 0x6e, 0x76, 0x37, 0x10, 0xe4, 0x93, 0xf8, 0xbd, 0xfa, 0xff, 0x81,
|
||||
0x21, 0x25, 0x86, 0x71, 0xac, 0xe0, 0xf5, 0xb7, 0xd2, 0x87, 0x8f, 0x98, 0x06, 0xca, 0x28, 0xe6,
|
||||
0x5e, 0xcf, 0x37, 0x99, 0x46, 0xb5, 0xaa, 0x3b, 0xf1, 0x97, 0x76, 0xeb, 0x3f, 0xec, 0x73, 0xa5,
|
||||
0xfa, 0x09, 0x37, 0x0f, 0x7a, 0xbe, 0xe9, 0x36, 0x7b, 0xad, 0xea, 0x8e, 0xfc, 0xd5, 0x0e, 0xf3,
|
||||
0x69, 0xf5, 0xc2, 0x4b, 0x2a, 0x21, 0x63, 0x3f, 0x19, 0xc6, 0xe8, 0xfd, 0x81, 0x58, 0x9a, 0x59,
|
||||
0xab, 0xba, 0xe3, 0x7e, 0xfd, 0x5e, 0x78, 0x7d, 0x1e, 0xa9, 0x6c, 0x8f, 0x2c, 0x4e, 0x97, 0x7f,
|
||||
0x07, 0x5b, 0xfd, 0xce, 0x78, 0x9d, 0x21, 0xc8, 0xdb, 0xc1, 0x7a, 0xd2, 0xdd, 0x4f, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x97, 0xbf, 0x9f, 0x8e, 0x6a, 0x01, 0x00, 0x00,
|
||||
}
|
||||
15
common/net/destination.proto
Normal file
15
common/net/destination.proto
Normal file
@@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.net;
|
||||
option go_package = "net";
|
||||
option java_package = "com.v2ray.core.common.net";
|
||||
option java_outer_classname = "DestinationProto";
|
||||
|
||||
import "v2ray.com/core/common/net/network.proto";
|
||||
import "v2ray.com/core/common/net/address.proto";
|
||||
|
||||
message Endpoint {
|
||||
Network network = 1;
|
||||
IPOrDomain address = 2;
|
||||
uint32 port = 3;
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package net_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestTCPDestination(t *testing.T) {
|
||||
@@ -29,7 +29,7 @@ func TestTCPDestinationEquals(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
dest := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
|
||||
assert.Bool(dest.Equals(nil)).IsFalse()
|
||||
assert.Bool(dest.Equals(v2net.Destination{})).IsFalse()
|
||||
|
||||
dest2 := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
|
||||
assert.Bool(dest.Equals(dest2)).IsTrue()
|
||||
@@ -45,7 +45,7 @@ func TestUDPDestinationEquals(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
dest := v2net.UDPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
|
||||
assert.Bool(dest.Equals(nil)).IsFalse()
|
||||
assert.Bool(dest.Equals(v2net.Destination{})).IsFalse()
|
||||
|
||||
dest2 := v2net.UDPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
|
||||
assert.Bool(dest.Equals(dest2)).IsTrue()
|
||||
|
||||
@@ -13,12 +13,8 @@ type IPNet struct {
|
||||
}
|
||||
|
||||
func NewIPNet() *IPNet {
|
||||
return NewIPNetInitialValue(make(map[uint32]byte, 1024))
|
||||
}
|
||||
|
||||
func NewIPNetInitialValue(data map[uint32]byte) *IPNet {
|
||||
return &IPNet{
|
||||
cache: data,
|
||||
cache: make(map[uint32]byte, 1024),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +41,15 @@ func (this *IPNet) Add(ipNet *net.IPNet) {
|
||||
// For now, we don't support IPv6
|
||||
return
|
||||
}
|
||||
value := ipToUint32(ipv4)
|
||||
mask := ipMaskToByte(ipNet.Mask)
|
||||
existing, found := this.cache[value]
|
||||
this.AddIP(ipv4, mask)
|
||||
}
|
||||
|
||||
func (this *IPNet) AddIP(ip []byte, mask byte) {
|
||||
k := ipToUint32(ip)
|
||||
existing, found := this.cache[k]
|
||||
if !found || existing > mask {
|
||||
this.cache[value] = mask
|
||||
this.cache[k] = mask
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func (this *IPNet) Contains(ip net.IP) bool {
|
||||
originalValue := ipToUint32(ipv4)
|
||||
|
||||
if entry, found := this.cache[originalValue]; found {
|
||||
if entry == 0 {
|
||||
if entry == 32 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -80,12 +80,8 @@ func (this *IPNet) Contains(ip net.IP) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (this *IPNet) Serialize() []uint32 {
|
||||
content := make([]uint32, 0, 2*len(this.cache))
|
||||
for key, value := range this.cache {
|
||||
content = append(content, uint32(key), uint32(value))
|
||||
}
|
||||
return content
|
||||
func (this *IPNet) IsEmpty() bool {
|
||||
return len(this.cache) == 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
. "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func parseCIDR(str string) *net.IPNet {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// Package net contains common network utilities.
|
||||
package net // import "github.com/v2ray/v2ray-core/common/net"
|
||||
package net
|
||||
|
||||
@@ -2,51 +2,68 @@ package net
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/collect"
|
||||
)
|
||||
|
||||
const (
|
||||
// TCPNetwork represents the TCP network.
|
||||
TCPNetwork = Network("tcp")
|
||||
|
||||
// UDPNetwork represents the UDP network.
|
||||
UDPNetwork = Network("udp")
|
||||
|
||||
// KCPNetwork represents the KCP network.
|
||||
KCPNetwork = Network("kcp")
|
||||
)
|
||||
|
||||
// Network represents a communication network on internet.
|
||||
type Network string
|
||||
func ParseNetwork(nwStr string) Network {
|
||||
if network, found := Network_value[nwStr]; found {
|
||||
return Network(network)
|
||||
}
|
||||
switch strings.ToLower(nwStr) {
|
||||
case "tcp":
|
||||
return Network_TCP
|
||||
case "udp":
|
||||
return Network_UDP
|
||||
case "kcp":
|
||||
return Network_KCP
|
||||
case "ws":
|
||||
return Network_WebSocket
|
||||
default:
|
||||
return Network_Unknown
|
||||
}
|
||||
}
|
||||
|
||||
func (this Network) AsList() *NetworkList {
|
||||
list := NetworkList([]Network{this})
|
||||
return &list
|
||||
}
|
||||
|
||||
func (this Network) String() string {
|
||||
return string(this)
|
||||
}
|
||||
|
||||
// NetworkList is a list of Networks.
|
||||
type NetworkList []Network
|
||||
|
||||
// NewNetworkList construsts a NetWorklist from the given StringListeralList.
|
||||
func NewNetworkList(networks collect.StringList) NetworkList {
|
||||
list := NetworkList(make([]Network, networks.Len()))
|
||||
for idx, network := range networks {
|
||||
list[idx] = Network(strings.ToLower(strings.TrimSpace(network)))
|
||||
return &NetworkList{
|
||||
Network: []Network{this},
|
||||
}
|
||||
}
|
||||
|
||||
func (this Network) SystemString() string {
|
||||
switch this {
|
||||
case Network_TCP, Network_RawTCP:
|
||||
return "tcp"
|
||||
case Network_UDP, Network_KCP:
|
||||
return "udp"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (this Network) UrlPrefix() string {
|
||||
switch this {
|
||||
case Network_TCP, Network_RawTCP:
|
||||
return "tcp"
|
||||
case Network_UDP:
|
||||
return "udp"
|
||||
case Network_KCP:
|
||||
return "kcp"
|
||||
case Network_WebSocket:
|
||||
return "ws"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// HashNetwork returns true if the given network is in this NetworkList.
|
||||
func (this *NetworkList) HasNetwork(network Network) bool {
|
||||
for _, value := range *this {
|
||||
func (this NetworkList) HasNetwork(network Network) bool {
|
||||
for _, value := range this.Network {
|
||||
if string(value) == string(network) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this NetworkList) Get(idx int) Network {
|
||||
return this.Network[idx]
|
||||
}
|
||||
|
||||
82
common/net/network.pb.go
Normal file
82
common/net/network.pb.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/common/net/network.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
package net
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type Network int32
|
||||
|
||||
const (
|
||||
Network_Unknown Network = 0
|
||||
// Native TCP provided by system.
|
||||
Network_RawTCP Network = 1
|
||||
// V2Ray specific TCP.
|
||||
Network_TCP Network = 2
|
||||
Network_UDP Network = 3
|
||||
Network_KCP Network = 4
|
||||
Network_WebSocket Network = 5
|
||||
)
|
||||
|
||||
var Network_name = map[int32]string{
|
||||
0: "Unknown",
|
||||
1: "RawTCP",
|
||||
2: "TCP",
|
||||
3: "UDP",
|
||||
4: "KCP",
|
||||
5: "WebSocket",
|
||||
}
|
||||
var Network_value = map[string]int32{
|
||||
"Unknown": 0,
|
||||
"RawTCP": 1,
|
||||
"TCP": 2,
|
||||
"UDP": 3,
|
||||
"KCP": 4,
|
||||
"WebSocket": 5,
|
||||
}
|
||||
|
||||
func (x Network) String() string {
|
||||
return proto.EnumName(Network_name, int32(x))
|
||||
}
|
||||
func (Network) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
|
||||
|
||||
type NetworkList struct {
|
||||
Network []Network `protobuf:"varint,1,rep,packed,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
|
||||
}
|
||||
|
||||
func (m *NetworkList) Reset() { *m = NetworkList{} }
|
||||
func (m *NetworkList) String() string { return proto.CompactTextString(m) }
|
||||
func (*NetworkList) ProtoMessage() {}
|
||||
func (*NetworkList) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*NetworkList)(nil), "v2ray.core.common.net.NetworkList")
|
||||
proto.RegisterEnum("v2ray.core.common.net.Network", Network_name, Network_value)
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/common/net/network.proto", fileDescriptor2) }
|
||||
|
||||
var fileDescriptor2 = []byte{
|
||||
// 203 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x33, 0x2a, 0x4a,
|
||||
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcd, 0xcd,
|
||||
0xcf, 0xd3, 0xcf, 0x4b, 0x2d, 0x01, 0xe1, 0xf2, 0xfc, 0xa2, 0x6c, 0xbd, 0x82, 0xa2, 0xfc, 0x92,
|
||||
0x7c, 0x21, 0x51, 0x98, 0xc2, 0xa2, 0x54, 0x3d, 0x88, 0x22, 0xbd, 0xbc, 0xd4, 0x12, 0x25, 0x77,
|
||||
0x2e, 0x6e, 0x3f, 0x88, 0x3a, 0x9f, 0xcc, 0xe2, 0x12, 0x21, 0x0b, 0x2e, 0x76, 0xa8, 0x36, 0x09,
|
||||
0x46, 0x05, 0x66, 0x0d, 0x3e, 0x23, 0x39, 0x3d, 0xac, 0xfa, 0xf4, 0xa0, 0x9a, 0x82, 0x60, 0xca,
|
||||
0xb5, 0x7c, 0xb8, 0xd8, 0xa1, 0x62, 0x42, 0xdc, 0x5c, 0xec, 0xa1, 0x79, 0xd9, 0x79, 0xf9, 0xe5,
|
||||
0x79, 0x02, 0x0c, 0x42, 0x5c, 0x5c, 0x6c, 0x41, 0x89, 0xe5, 0x21, 0xce, 0x01, 0x02, 0x8c, 0x42,
|
||||
0xec, 0x5c, 0xcc, 0x20, 0x06, 0x13, 0x88, 0x11, 0xea, 0x12, 0x20, 0xc0, 0x0c, 0x62, 0x78, 0x3b,
|
||||
0x07, 0x08, 0xb0, 0x08, 0xf1, 0x72, 0x71, 0x86, 0xa7, 0x26, 0x05, 0xe7, 0x27, 0x67, 0xa7, 0x96,
|
||||
0x08, 0xb0, 0x3a, 0xe9, 0x71, 0x49, 0x26, 0xe7, 0xe7, 0x62, 0xb7, 0xdb, 0x89, 0x07, 0x6a, 0x51,
|
||||
0x00, 0xc8, 0x63, 0x51, 0xcc, 0x79, 0xa9, 0x25, 0x49, 0x6c, 0x60, 0x4f, 0x1a, 0x03, 0x02, 0x00,
|
||||
0x00, 0xff, 0xff, 0x6e, 0x52, 0xf1, 0x92, 0x0f, 0x01, 0x00, 0x00,
|
||||
}
|
||||
26
common/net/network.proto
Normal file
26
common/net/network.proto
Normal file
@@ -0,0 +1,26 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.net;
|
||||
option go_package = "net";
|
||||
option java_package = "com.v2ray.core.common.net";
|
||||
option java_outer_classname = "NetworkProto";
|
||||
|
||||
enum Network {
|
||||
Unknown = 0;
|
||||
|
||||
// Native TCP provided by system.
|
||||
RawTCP = 1;
|
||||
|
||||
// V2Ray specific TCP.
|
||||
TCP = 2;
|
||||
|
||||
UDP = 3;
|
||||
|
||||
KCP = 4;
|
||||
|
||||
WebSocket = 5;
|
||||
}
|
||||
|
||||
message NetworkList {
|
||||
repeated Network network = 1;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/collect"
|
||||
)
|
||||
|
||||
func (this *NetworkList) UnmarshalJSON(data []byte) error {
|
||||
var strlist collect.StringList
|
||||
if err := json.Unmarshal(data, &strlist); err != nil {
|
||||
return err
|
||||
}
|
||||
*this = NewNetworkList(strlist)
|
||||
return nil
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package net_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
)
|
||||
|
||||
func TestArrayNetworkList(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var list NetworkList
|
||||
err := json.Unmarshal([]byte("[\"Tcp\"]"), &list)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Bool(list.HasNetwork(Network("tcp"))).IsTrue()
|
||||
assert.Bool(list.HasNetwork(Network("udp"))).IsFalse()
|
||||
}
|
||||
|
||||
func TestStringNetworkList(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var list NetworkList
|
||||
err := json.Unmarshal([]byte("\"TCP, ip\""), &list)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Bool(list.HasNetwork(Network("tcp"))).IsTrue()
|
||||
assert.Bool(list.HasNetwork(Network("udp"))).IsFalse()
|
||||
}
|
||||
|
||||
func TestInvalidNetworkJson(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var list NetworkList
|
||||
err := json.Unmarshal([]byte("0"), &list)
|
||||
assert.Error(err).IsNotNil()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user