You've already forked v2ray-core
Compare commits
193 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
cc92973daf | ||
|
|
ccf1bf25b6 | ||
|
|
07dee80f54 | ||
|
|
4419f1e3d6 | ||
|
|
a9d583b92f | ||
|
|
a2651f4dfc | ||
|
|
fed2933043 | ||
|
|
5e576e11bb | ||
|
|
49441a5050 | ||
|
|
a0fda39274 | ||
|
|
3e9e9b520e | ||
|
|
1fe090dbfd | ||
|
|
427bed5ddb | ||
|
|
16b529093d | ||
|
|
fecf9cc5b8 | ||
|
|
7ef66c57dc | ||
|
|
29f69d63c4 | ||
|
|
20f16309e6 | ||
|
|
0d60d2449a | ||
|
|
2eced2bd6c | ||
|
|
8c4a6d94f9 | ||
|
|
8c96b1961b | ||
|
|
508f79f95f | ||
|
|
cb1356be75 | ||
|
|
bcd27ba36f | ||
|
|
a43ee2f1c2 | ||
|
|
f03c86f468 | ||
|
|
9e997a5be7 | ||
|
|
25b30704a4 | ||
|
|
5dc80a2cc5 | ||
|
|
0b2df7f658 | ||
|
|
27f3401848 | ||
|
|
697d44abbd | ||
|
|
c6ad190f0a | ||
|
|
dbf5f948cd | ||
|
|
b01a972076 | ||
|
|
b38137bd13 |
20
.travis.yml
20
.travis.yml
@@ -1,16 +1,16 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6.3
|
||||
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/onsi/gomega
|
||||
- go get github.com/onsi/ginkgo
|
||||
- 1.7.1
|
||||
|
||||
script:
|
||||
- go test -tags json github.com/v2ray/v2ray-core/...
|
||||
go_import_path: v2ray.com/core
|
||||
|
||||
git:
|
||||
depth: 5
|
||||
|
||||
script:
|
||||
- go test -tags json v2ray.com/core/...
|
||||
|
||||
after_success:
|
||||
- ./testing/coverage/coverall
|
||||
|
||||
@@ -21,7 +21,7 @@ before_deploy:
|
||||
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="
|
||||
secure: "FORkI+hXFWSxLkqkBDvo8APQ1XLfuzbOBqhVW474x299AzHpgE/7dYLNo/rQaerYMdmw8gB21tUWOI3FjUYv51x1dO2a2Bu8Por+1BQ+zdUIyS3zJteJ8bAMZGVtg1BCTFjxQsIDMmaziaScSKz3NwEJ1IL8UIBiidFf8EuYyK+EL6yQFodrSeUDsUH52pBO0SBugsAj4lOSTCS25ZcpWYcUMBo7zaD9sNE1Oo8f/bz7cFe4cJLCpazIgkt57IT3u/8BH/EMz4HRbAqj48mjKytp4lm7R3IC8w0ba6yLNXgKqva10B/KNwZQweXqglM5iawQDdSbnIjUnVEe9Oexu8wNV52oBt+8wC7P/ZtAsZTnyWvwIhH2uyhzEHfsM5Up7DnAnaATh/+2upn3lcs4s2p9d/6tIObeIpBvP/3QRNmlmtZFIOnlqkcROj9NQ3IHGbswGiAfBDAsAC8h9CRDy9MtRs6ZbaCih0FLgMzEXi+S50eelNRv4SGaeLlW07cz7uma5C+z+zWb4ZmWsOwWjkOAaFL/zL5O9/w7i4cbXr/sQ6z6YmdDEejbrkHiE8DmKQqeV13xY1FhDqFyEpsdUbftG6pKPt5wcyNEAnw9aPMK7Ec0dAe6vg+oTcfMPAO/rHRXEc4IP56QqdlZTmsZOdDrGgnkRxpbayc+KcvrN28="
|
||||
file:
|
||||
- "$GOPATH/bin/v2ray-macos.zip"
|
||||
- "$GOPATH/bin/v2ray-windows-64.zip"
|
||||
@@ -33,6 +33,8 @@ deploy:
|
||||
- "$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:
|
||||
|
||||
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"
|
||||
|
||||
|
||||
26
all.go
Normal file
26
all.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
// The following are necessary as they register handlers in their init functions.
|
||||
_ "v2ray.com/core/app/dns"
|
||||
_ "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/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"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"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(destination v2net.Destination) ray.InboundRay
|
||||
DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay
|
||||
}
|
||||
|
||||
@@ -1,18 +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/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 {
|
||||
@@ -23,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.")
|
||||
@@ -32,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
|
||||
@@ -42,9 +43,10 @@ func (this *DefaultDispatcher) Release() {
|
||||
|
||||
}
|
||||
|
||||
func (this *DefaultDispatcher) DispatchToOutbound(destination v2net.Destination) ray.InboundRay {
|
||||
func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, 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 {
|
||||
@@ -59,12 +61,16 @@ func (this *DefaultDispatcher) DispatchToOutbound(destination v2net.Destination)
|
||||
}
|
||||
}
|
||||
|
||||
go this.FilterPacketAndDispatch(destination, direct, dispatcher)
|
||||
if meta.AllowPassiveConnection {
|
||||
go dispatcher.Dispatch(destination, alloc.NewLocalBuffer(32).Clear(), direct)
|
||||
} else {
|
||||
go this.FilterPacketAndDispatch(destination, direct, dispatcher)
|
||||
}
|
||||
|
||||
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,8 +1,9 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"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 {
|
||||
@@ -29,10 +30,10 @@ func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic
|
||||
}
|
||||
}
|
||||
|
||||
func (this *TestPacketDispatcher) DispatchToOutbound(destination v2net.Destination) ray.InboundRay {
|
||||
func (this *TestPacketDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay {
|
||||
traffic := ray.NewRay()
|
||||
this.Destination <- destination
|
||||
go this.Handler(destination, traffic)
|
||||
this.Destination <- session.Destination
|
||||
go this.Handler(session.Destination, traffic)
|
||||
|
||||
return 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
|
||||
}
|
||||
|
||||
82
app/dns/config.pb.go
Normal file
82
app/dns/config.pb.go
Normal file
@@ -0,0 +1,82 @@
|
||||
// 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 []*v2ray_core_common_net2.Endpoint `protobuf:"bytes,1,rep,name=NameServers" json:"NameServers,omitempty"`
|
||||
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,
|
||||
}
|
||||
14
app/dns/config.proto
Normal file
14
app/dns/config.proto
Normal file
@@ -0,0 +1,14 @@
|
||||
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 {
|
||||
repeated v2ray.core.common.net.Endpoint NameServers = 1;
|
||||
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.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,12 +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/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"
|
||||
)
|
||||
@@ -49,14 +50,16 @@ type UDPNameServer struct {
|
||||
|
||||
func NewUDPNameServer(address v2net.Destination, dispatcher dispatcher.PacketDispatcher) *UDPNameServer {
|
||||
s := &UDPNameServer{
|
||||
address: address,
|
||||
requests: make(map[uint16]*PendingRequest),
|
||||
udpServer: udp.NewUDPServer(dispatcher),
|
||||
address: address,
|
||||
requests: make(map[uint16]*PendingRequest),
|
||||
udpServer: udp.NewUDPServer(&proxy.InboundHandlerMeta{
|
||||
AllowPassiveConnection: false,
|
||||
}, dispatcher),
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// @Private
|
||||
// Private: Visible for testing.
|
||||
func (this *UDPNameServer) Cleanup() {
|
||||
expiredRequests := make([]uint16, 0, 16)
|
||||
now := time.Now()
|
||||
@@ -74,7 +77,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()
|
||||
@@ -99,7 +102,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)
|
||||
@@ -162,7 +165,7 @@ func (this *UDPNameServer) BuildQueryA(domain string, id uint16) *alloc.Buffer {
|
||||
}
|
||||
|
||||
func (this *UDPNameServer) DispatchQuery(payload *alloc.Buffer) {
|
||||
this.udpServer.Dispatch(pseudoDestination, this.address, payload, this.HandleResponse)
|
||||
this.udpServer.Dispatch(&proxy.SessionInfo{Source: pseudoDestination, Destination: this.address}, payload, this.HandleResponse)
|
||||
}
|
||||
|
||||
func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord {
|
||||
|
||||
@@ -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().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{})
|
||||
}
|
||||
|
||||
@@ -4,16 +4,16 @@ 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"
|
||||
"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"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
"v2ray.com/core/proxy"
|
||||
"v2ray.com/core/proxy/freedom"
|
||||
"v2ray.com/core/testing/assert"
|
||||
"v2ray.com/core/transport/internet"
|
||||
)
|
||||
|
||||
func TestDnsAdd(t *testing.T) {
|
||||
@@ -28,8 +28,8 @@ func TestDnsAdd(t *testing.T) {
|
||||
space,
|
||||
&proxy.OutboundHandlerMeta{
|
||||
Address: v2net.AnyIP,
|
||||
StreamSettings: &internet.StreamSettings{
|
||||
Type: internet.StreamConnectionTypeRawTCP,
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
Network: v2net.Network_RawTCP,
|
||||
},
|
||||
}))
|
||||
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager)
|
||||
@@ -37,9 +37,15 @@ func TestDnsAdd(t *testing.T) {
|
||||
|
||||
domain := "local.v2ray.com"
|
||||
server := NewCacheServer(space, &Config{
|
||||
NameServers: []v2net.Destination{
|
||||
v2net.UDPDestination(v2net.IPAddress([]byte{8, 8, 8, 8}), v2net.Port(53)),
|
||||
},
|
||||
NameServers: []*v2net.Endpoint{{
|
||||
Network: v2net.Network_UDP,
|
||||
Address: &v2net.IPOrDomain{
|
||||
Address: &v2net.IPOrDomain_Ip{
|
||||
Ip: []byte{8, 8, 8, 8},
|
||||
},
|
||||
},
|
||||
Port: 53,
|
||||
}},
|
||||
})
|
||||
space.BindApp(APP_ID, server)
|
||||
space.Initialize()
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package rules
|
||||
package router
|
||||
|
||||
import (
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
v2net "v2ray.com/core/common/net"
|
||||
)
|
||||
|
||||
type Condition interface {
|
||||
@@ -73,10 +73,10 @@ func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
|
||||
}
|
||||
|
||||
func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().IsDomain() {
|
||||
if !dest.Address.Family().IsDomain() {
|
||||
return false
|
||||
}
|
||||
domain := dest.Address().Domain()
|
||||
domain := dest.Address.Domain()
|
||||
return strings.Contains(domain, this.pattern)
|
||||
}
|
||||
|
||||
@@ -95,10 +95,10 @@ func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
|
||||
}
|
||||
|
||||
func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().IsDomain() {
|
||||
if !dest.Address.Family().IsDomain() {
|
||||
return false
|
||||
}
|
||||
domain := dest.Address().Domain()
|
||||
domain := dest.Address.Domain()
|
||||
return this.pattern.MatchString(strings.ToLower(domain))
|
||||
}
|
||||
|
||||
@@ -106,10 +106,10 @@ type CIDRMatcher struct {
|
||||
cidr *net.IPNet
|
||||
}
|
||||
|
||||
func NewCIDRMatcher(ipnet string) (*CIDRMatcher, error) {
|
||||
_, cidr, err := net.ParseCIDR(ipnet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func NewCIDRMatcher(ip []byte, mask uint32) (*CIDRMatcher, error) {
|
||||
cidr := &net.IPNet{
|
||||
IP: net.IP(ip),
|
||||
Mask: net.CIDRMask(int(mask), len(ip)),
|
||||
}
|
||||
return &CIDRMatcher{
|
||||
cidr: cidr,
|
||||
@@ -117,10 +117,10 @@ func NewCIDRMatcher(ipnet string) (*CIDRMatcher, error) {
|
||||
}
|
||||
|
||||
func (this *CIDRMatcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().IsIPv4() && !dest.Address().IsIPv6() {
|
||||
if !dest.Address.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
|
||||
return false
|
||||
}
|
||||
return this.cidr.Contains(dest.Address().IP())
|
||||
return this.cidr.Contains(dest.Address.IP())
|
||||
}
|
||||
|
||||
type IPv4Matcher struct {
|
||||
@@ -134,10 +134,10 @@ func NewIPv4Matcher(ipnet *v2net.IPNet) *IPv4Matcher {
|
||||
}
|
||||
|
||||
func (this *IPv4Matcher) Apply(dest v2net.Destination) bool {
|
||||
if !dest.Address().IsIPv4() {
|
||||
if !dest.Address.Family().Either(v2net.AddressFamilyIPv4) {
|
||||
return false
|
||||
}
|
||||
return this.ipv4net.Contains(dest.Address().IP())
|
||||
return this.ipv4net.Contains(dest.Address.IP())
|
||||
}
|
||||
|
||||
type PortMatcher struct {
|
||||
@@ -151,7 +151,7 @@ func NewPortMatcher(portRange v2net.PortRange) *PortMatcher {
|
||||
}
|
||||
|
||||
func (this *PortMatcher) Apply(dest v2net.Destination) bool {
|
||||
return this.port.Contains(dest.Port())
|
||||
return this.port.Contains(dest.Port)
|
||||
}
|
||||
|
||||
type NetworkMatcher struct {
|
||||
@@ -165,5 +165,5 @@ func NewNetworkMatcher(network *v2net.NetworkList) *NetworkMatcher {
|
||||
}
|
||||
|
||||
func (this *NetworkMatcher) Apply(dest v2net.Destination) bool {
|
||||
return this.network.HasNetwork(dest.Network())
|
||||
return this.network.HasNetwork(dest.Network)
|
||||
}
|
||||
@@ -1,6 +1,85 @@
|
||||
package router
|
||||
|
||||
type Config struct {
|
||||
Strategy string
|
||||
Settings interface{}
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
v2net "v2ray.com/core/common/net"
|
||||
)
|
||||
|
||||
type Rule struct {
|
||||
Tag string
|
||||
Condition Condition
|
||||
}
|
||||
|
||||
func (this *Rule) Apply(dest v2net.Destination) bool {
|
||||
return this.Condition.Apply(dest)
|
||||
}
|
||||
|
||||
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.Ip) > 0 {
|
||||
ipv4Net := make(map[uint32]byte)
|
||||
ipv6Cond := NewAnyCondition()
|
||||
hasIpv6 := false
|
||||
|
||||
for _, ip := range this.Ip {
|
||||
switch len(ip.Ip) {
|
||||
case net.IPv4len:
|
||||
k := (uint32(ip.Ip[0]) << 24) + (uint32(ip.Ip[1]) << 16) + (uint32(ip.Ip[2]) << 8) + uint32(ip.Ip[3])
|
||||
ipv4Net[k] = byte(32 - ip.UnmatchingBits)
|
||||
case net.IPv6len:
|
||||
hasIpv6 = true
|
||||
matcher, err := NewCIDRMatcher(ip.Ip, uint32(32)-ip.UnmatchingBits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ipv6Cond.Add(matcher)
|
||||
default:
|
||||
return nil, errors.New("Router: Invalid IP length.")
|
||||
}
|
||||
}
|
||||
|
||||
if len(ipv4Net) > 0 && hasIpv6 {
|
||||
cond := NewAnyCondition()
|
||||
cond.Add(NewIPv4Matcher(v2net.NewIPNetInitialValue(ipv4Net)))
|
||||
cond.Add(ipv6Cond)
|
||||
conds.Add(cond)
|
||||
} else if len(ipv4Net) > 0 {
|
||||
conds.Add(NewIPv4Matcher(v2net.NewIPNetInitialValue(ipv4Net)))
|
||||
} 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 conds.Len() == 0 {
|
||||
return nil, errors.New("Router: This rule has no effective fields.")
|
||||
}
|
||||
|
||||
return conds, nil
|
||||
}
|
||||
|
||||
212
app/router/config.pb.go
Normal file
212
app/router/config.pb.go
Normal file
@@ -0,0 +1,212 @@
|
||||
// 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
|
||||
IP
|
||||
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 (
|
||||
Config_AsIs Config_DomainStrategy = 0
|
||||
Config_UseIp Config_DomainStrategy = 1
|
||||
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.
|
||||
type IP struct {
|
||||
// IP address, should be either 4 or 16 bytes.
|
||||
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||
// Number of right-most bits in IP matching that is allowed.
|
||||
// Single IP address like 127.0.0.1 should use unmatching_bits = 0.
|
||||
// CIDR 10.0.0.0/8 should use unmatching_bits = 32-8 = 24.
|
||||
UnmatchingBits uint32 `protobuf:"varint,2,opt,name=unmatching_bits,json=unmatchingBits" json:"unmatching_bits,omitempty"`
|
||||
}
|
||||
|
||||
func (m *IP) Reset() { *m = IP{} }
|
||||
func (m *IP) String() string { return proto.CompactTextString(m) }
|
||||
func (*IP) ProtoMessage() {}
|
||||
func (*IP) 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"`
|
||||
Ip []*IP `protobuf:"bytes,3,rep,name=ip" json:"ip,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"`
|
||||
}
|
||||
|
||||
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) GetIp() []*IP {
|
||||
if m != nil {
|
||||
return m.Ip
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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((*IP)(nil), "v2ray.core.app.router.IP")
|
||||
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{
|
||||
// 462 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x92, 0x5f, 0x6b, 0xd5, 0x30,
|
||||
0x18, 0xc6, 0x6d, 0x77, 0x4e, 0xf1, 0xbc, 0x3d, 0x76, 0x25, 0x28, 0x74, 0x43, 0xa1, 0x14, 0x71,
|
||||
0x47, 0x90, 0x54, 0x8e, 0xa8, 0x57, 0x22, 0x1e, 0xf5, 0xa2, 0xa0, 0xa3, 0x44, 0x77, 0xe3, 0xcd,
|
||||
0x21, 0xeb, 0xb2, 0x1a, 0x6c, 0x93, 0x90, 0xa6, 0xd3, 0xf3, 0x11, 0xfc, 0x76, 0x7e, 0x24, 0x69,
|
||||
0xd2, 0xb1, 0x4d, 0x56, 0xef, 0xf2, 0x86, 0xdf, 0xf3, 0xfe, 0x7d, 0xe0, 0xc9, 0xc5, 0x5a, 0xd3,
|
||||
0x1d, 0xae, 0x64, 0x9b, 0x57, 0x52, 0xb3, 0x9c, 0x2a, 0x95, 0x6b, 0xd9, 0x1b, 0xa6, 0xf3, 0x4a,
|
||||
0x8a, 0x73, 0x5e, 0x63, 0xa5, 0xa5, 0x91, 0xe8, 0xc1, 0x25, 0xa7, 0x19, 0xa6, 0x4a, 0x61, 0xc7,
|
||||
0x1c, 0x3e, 0xfe, 0x47, 0x5e, 0xc9, 0xb6, 0x95, 0x22, 0x17, 0xcc, 0xe4, 0x4a, 0x6a, 0xe3, 0xc4,
|
||||
0x87, 0x47, 0xd3, 0x94, 0x60, 0xe6, 0xa7, 0xd4, 0x3f, 0x1c, 0x98, 0x19, 0x08, 0x3e, 0xc8, 0x96,
|
||||
0x72, 0x81, 0x5e, 0xc1, 0xcc, 0xec, 0x14, 0x4b, 0xbc, 0xd4, 0x5b, 0x45, 0xeb, 0x0c, 0xdf, 0x5a,
|
||||
0x1e, 0x3b, 0x18, 0x7f, 0xdd, 0x29, 0x46, 0x2c, 0x8f, 0xee, 0xc3, 0xfc, 0x82, 0x36, 0x3d, 0x4b,
|
||||
0xfc, 0xd4, 0x5b, 0x2d, 0x88, 0x0b, 0xb2, 0x87, 0x30, 0x1b, 0x18, 0xb4, 0x80, 0x79, 0xd9, 0x50,
|
||||
0x2e, 0xe2, 0x3b, 0xc3, 0x93, 0xb0, 0x9a, 0xfd, 0x8a, 0xbd, 0xec, 0x0d, 0xf8, 0x45, 0x89, 0x22,
|
||||
0xf0, 0xb9, 0xb2, 0xf5, 0x96, 0xc4, 0xe7, 0x0a, 0x1d, 0xc1, 0x7e, 0x2f, 0x5a, 0x6a, 0xaa, 0xef,
|
||||
0x5c, 0xd4, 0xdb, 0x53, 0x6e, 0x3a, 0x9b, 0xf3, 0x1e, 0x89, 0xae, 0xbe, 0x37, 0xdc, 0x74, 0xd9,
|
||||
0x6f, 0x1f, 0x42, 0x22, 0x7b, 0xc3, 0x45, 0x4d, 0xfa, 0x86, 0xa1, 0x18, 0xf6, 0x0c, 0xad, 0x6d,
|
||||
0xa6, 0x05, 0x19, 0x9e, 0xe8, 0x25, 0x04, 0x67, 0xb6, 0xd3, 0xc4, 0x4f, 0xf7, 0x56, 0xe1, 0xfa,
|
||||
0xd1, 0x7f, 0xc7, 0x21, 0x23, 0x8c, 0x9e, 0xda, 0x8e, 0xf6, 0xac, 0xe4, 0x60, 0x42, 0x52, 0x94,
|
||||
0xb6, 0xd9, 0xb7, 0x00, 0xc3, 0xbe, 0xb7, 0x9a, 0x8a, 0x9a, 0x25, 0xb3, 0xd4, 0x5b, 0x85, 0xeb,
|
||||
0xf4, 0xba, 0xc4, 0xad, 0x1c, 0x0b, 0x66, 0x70, 0x29, 0xb5, 0x21, 0x03, 0x47, 0x16, 0xea, 0xf2,
|
||||
0x89, 0x3e, 0xc2, 0x72, 0x3c, 0xc5, 0xb6, 0xe1, 0x9d, 0x49, 0xe6, 0x36, 0x45, 0x36, 0x91, 0xe2,
|
||||
0xd8, 0xa1, 0x9f, 0x78, 0x67, 0x48, 0x28, 0xae, 0x82, 0xec, 0x8f, 0x07, 0xc1, 0x7b, 0xeb, 0x1b,
|
||||
0x74, 0x02, 0xfb, 0x6e, 0x8e, 0x6d, 0x67, 0x34, 0x35, 0xac, 0xde, 0x8d, 0xc7, 0x7c, 0x36, 0x31,
|
||||
0x8a, 0xd3, 0x8d, 0x4b, 0xf8, 0x32, 0x6a, 0x48, 0x74, 0x76, 0x23, 0x1e, 0x8c, 0xa1, 0xfb, 0x86,
|
||||
0x8d, 0x9b, 0x9c, 0x32, 0xc6, 0xb5, 0x7b, 0x10, 0xcb, 0x67, 0xaf, 0x21, 0xba, 0x99, 0x19, 0xdd,
|
||||
0x85, 0xd9, 0xbb, 0xae, 0xe8, 0x9c, 0x17, 0x4e, 0x3a, 0x56, 0xa8, 0xd8, 0x43, 0x31, 0x2c, 0x0b,
|
||||
0x55, 0x9c, 0x1f, 0x4b, 0xf1, 0x79, 0xb8, 0x71, 0xec, 0x6f, 0x9e, 0xc3, 0x41, 0x25, 0xdb, 0xdb,
|
||||
0xeb, 0x6c, 0x42, 0xd7, 0x74, 0x39, 0xb8, 0xf7, 0x5b, 0xe0, 0x3e, 0x4f, 0x03, 0x6b, 0xe6, 0x17,
|
||||
0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x93, 0xed, 0x34, 0x36, 0x5c, 0x03, 0x00, 0x00,
|
||||
}
|
||||
55
app/router/config.proto
Normal file
55
app/router/config.proto
Normal file
@@ -0,0 +1,55 @@
|
||||
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.
|
||||
message IP {
|
||||
// IP address, should be either 4 or 16 bytes.
|
||||
bytes ip = 1;
|
||||
|
||||
// Number of right-most bits in IP matching that is allowed.
|
||||
// Single IP address like 127.0.0.1 should use unmatching_bits = 0.
|
||||
// CIDR 10.0.0.0/8 should use unmatching_bits = 32-8 = 24.
|
||||
uint32 unmatching_bits = 2;
|
||||
}
|
||||
|
||||
message RoutingRule {
|
||||
string tag = 1;
|
||||
repeated Domain domain = 2;
|
||||
repeated IP ip = 3;
|
||||
v2ray.core.common.net.PortRange port_range = 4;
|
||||
v2ray.core.common.net.NetworkList network_list = 5;
|
||||
}
|
||||
|
||||
message Config {
|
||||
enum DomainStrategy {
|
||||
AsIs = 0;
|
||||
UseIp = 1;
|
||||
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,125 @@
|
||||
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"
|
||||
)
|
||||
|
||||
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(dest v2net.Destination) (string, error) {
|
||||
for _, rule := range this.rules {
|
||||
if rule.Apply(dest) {
|
||||
return rule.Tag, nil
|
||||
}
|
||||
}
|
||||
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(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 (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{})
|
||||
}
|
||||
|
||||
41
app/router/router_test.go
Normal file
41
app/router/router_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
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/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(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,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().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
|
||||
|
||||
@@ -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
|
||||
@@ -51,10 +53,32 @@ 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 (
|
||||
smallPool = NewBufferPool(1600, 256)
|
||||
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) {
|
||||
|
||||
@@ -7,6 +7,6 @@ func NewStringList(raw []string) *StringList {
|
||||
return &list
|
||||
}
|
||||
|
||||
func (this *StringList) Len() int {
|
||||
return len(*this)
|
||||
func (this StringList) Len() int {
|
||||
return len(this)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
. "github.com/v2ray/v2ray-core/common/collect"
|
||||
"github.com/v2ray/v2ray-core/testing/assert"
|
||||
. "v2ray.com/core/common/collect"
|
||||
"v2ray.com/core/testing/assert"
|
||||
)
|
||||
|
||||
func TestStringListUnmarshalError(t *testing.T) {
|
||||
@@ -18,3 +18,13 @@ func TestStringListUnmarshalError(t *testing.T) {
|
||||
err := json.Unmarshal([]byte(rawJson), list)
|
||||
assert.Error(err).IsNotNil()
|
||||
}
|
||||
|
||||
func TestStringListLen(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
rawJson := `"a, b, c, d"`
|
||||
list := new(StringList)
|
||||
err := json.Unmarshal([]byte(rawJson), list)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Int(list.Len()).Equals(4)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -22,7 +22,7 @@ func NewChanReader(stream Reader) *ChanReader {
|
||||
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) {
|
||||
|
||||
@@ -2,46 +2,35 @@ package loader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrConfigIDKeyNotFound = errors.New("Config ID key is not found.")
|
||||
ErrConfigIDExists = errors.New("Config ID already exists.")
|
||||
ErrUnknownConfigID = errors.New("Unknown config ID.")
|
||||
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 ConfigCreatorCache map[string]ConfigCreator
|
||||
|
||||
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
|
||||
func (this ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error {
|
||||
if _, found := this[id]; found {
|
||||
return common.ErrDuplicatedName
|
||||
}
|
||||
|
||||
this.creators[id] = creator
|
||||
this[id] = creator
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *BaseConfigLoader) CreateConfig(id string) (interface{}, error) {
|
||||
creator, found := this.creators[id]
|
||||
func (this ConfigCreatorCache) CreateConfig(id string) (interface{}, error) {
|
||||
creator, found := this[id]
|
||||
if !found {
|
||||
return nil, ErrUnknownConfigID
|
||||
}
|
||||
return creator(), nil
|
||||
}
|
||||
|
||||
type ConfigLoader interface {
|
||||
Load([]byte) (interface{}, string, error)
|
||||
LoadWithID([]byte, string) (interface{}, error)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
59
common/loader/type.pb.go
Normal file
59
common/loader/type.pb.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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
|
||||
|
||||
type TypedSettings struct {
|
||||
Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
|
||||
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,
|
||||
}
|
||||
11
common/loader/type.proto
Normal file
11
common/loader/type.proto
Normal file
@@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.loader;
|
||||
option go_package = "loader";
|
||||
option java_package = "com.v2ray.core.common.loader";
|
||||
option java_outer_classname = "TypeProto";
|
||||
|
||||
message TypedSettings {
|
||||
string type = 1;
|
||||
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 (
|
||||
@@ -12,15 +12,41 @@ var (
|
||||
AnyIP = IPAddress([]byte{0, 0, 0, 0})
|
||||
)
|
||||
|
||||
type AddressFamily int
|
||||
|
||||
const (
|
||||
AddressFamilyIPv4 = AddressFamily(0)
|
||||
AddressFamilyIPv6 = AddressFamily(1)
|
||||
AddressFamilyDomain = AddressFamily(2)
|
||||
)
|
||||
|
||||
func (this AddressFamily) Either(fs ...AddressFamily) bool {
|
||||
for _, f := range fs {
|
||||
if this == f {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (this AddressFamily) IsIPv4() bool {
|
||||
return this == AddressFamilyIPv4
|
||||
}
|
||||
|
||||
func (this AddressFamily) IsIPv6() bool {
|
||||
return this == AddressFamilyIPv6
|
||||
}
|
||||
|
||||
func (this AddressFamily) IsDomain() bool {
|
||||
return this == AddressFamilyDomain
|
||||
}
|
||||
|
||||
// Address represents a network address to be communicated with. It may be an IP address or domain
|
||||
// address, not both. This interface doesn't resolve IP address for a given domain.
|
||||
type Address interface {
|
||||
IP() net.IP // IP of this Address
|
||||
Domain() string // Domain of this Address
|
||||
|
||||
IsIPv4() bool // True if this Address is an IPv4 address
|
||||
IsIPv6() bool // True if this Address is an IPv6 address
|
||||
IsDomain() bool // True if this Address is an domain address
|
||||
Family() AddressFamily
|
||||
|
||||
String() string // String representation of this Address
|
||||
Equals(Address) bool
|
||||
@@ -75,16 +101,8 @@ func (addr *ipv4Address) Domain() string {
|
||||
panic("Calling Domain() on an IPv4Address.")
|
||||
}
|
||||
|
||||
func (addr *ipv4Address) IsIPv4() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (addr *ipv4Address) IsIPv6() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (addr *ipv4Address) IsDomain() bool {
|
||||
return false
|
||||
func (addr *ipv4Address) Family() AddressFamily {
|
||||
return AddressFamilyIPv4
|
||||
}
|
||||
|
||||
func (this *ipv4Address) String() string {
|
||||
@@ -112,16 +130,8 @@ func (addr *ipv6Address) Domain() string {
|
||||
panic("Calling Domain() on an IPv6Address.")
|
||||
}
|
||||
|
||||
func (addr *ipv6Address) IsIPv4() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (addr *ipv6Address) IsIPv6() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (addr *ipv6Address) IsDomain() bool {
|
||||
return false
|
||||
func (this *ipv6Address) Family() AddressFamily {
|
||||
return AddressFamilyIPv6
|
||||
}
|
||||
|
||||
func (this *ipv6Address) String() string {
|
||||
@@ -161,16 +171,8 @@ func (addr *domainAddress) Domain() string {
|
||||
return string(*addr)
|
||||
}
|
||||
|
||||
func (addr *domainAddress) IsIPv4() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (addr *domainAddress) IsIPv6() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (addr *domainAddress) IsDomain() bool {
|
||||
return true
|
||||
func (addr *domainAddress) Family() AddressFamily {
|
||||
return AddressFamilyDomain
|
||||
}
|
||||
|
||||
func (this *domainAddress) String() string {
|
||||
@@ -184,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,
|
||||
}
|
||||
13
common/net/address.proto
Normal file
13
common/net/address.proto
Normal file
@@ -0,0 +1,13 @@
|
||||
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 {
|
||||
bytes ip = 1;
|
||||
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.IsIPv4()).IsTrue()
|
||||
assert.Bool(address.Address.IsDomain()).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.IsIPv4()).IsFalse()
|
||||
assert.Bool(address.Address.IsDomain()).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) {
|
||||
|
||||
@@ -1,116 +1,61 @@
|
||||
package net
|
||||
|
||||
// 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
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
IsTCP() bool // True if destination is reachable via TCP
|
||||
IsUDP() bool // True if destination is reachable via UDP
|
||||
// Destination represents a network destination including address and protocol (tcp / udp).
|
||||
type Destination struct {
|
||||
Network Network
|
||||
Address Address
|
||||
Port Port
|
||||
}
|
||||
|
||||
func DestinationFromAddr(addr net.Addr) Destination {
|
||||
switch addr := addr.(type) {
|
||||
case *net.TCPAddr:
|
||||
return TCPDestination(IPAddress(addr.IP), Port(addr.Port))
|
||||
case *net.UDPAddr:
|
||||
return UDPDestination(IPAddress(addr.IP), Port(addr.Port))
|
||||
default:
|
||||
panic("Unknown address type.")
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,50 +3,80 @@ package net
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/collect"
|
||||
"v2ray.com/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
|
||||
return &NetworkList{
|
||||
Network: []Network{this},
|
||||
}
|
||||
}
|
||||
|
||||
func (this Network) String() string {
|
||||
return string(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"
|
||||
}
|
||||
}
|
||||
|
||||
// NetworkList is a list of Networks.
|
||||
type NetworkList []Network
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
// NewNetworkList construsts a NetWorklist from the given StringListeralList.
|
||||
func NewNetworkList(networks collect.StringList) NetworkList {
|
||||
list := NetworkList(make([]Network, networks.Len()))
|
||||
func NewNetworkList(networks collect.StringList) *NetworkList {
|
||||
list := &NetworkList{
|
||||
Network: make([]Network, networks.Len()),
|
||||
}
|
||||
for idx, network := range networks {
|
||||
list[idx] = Network(strings.ToLower(strings.TrimSpace(network)))
|
||||
list.Network[idx] = ParseNetwork(network)
|
||||
}
|
||||
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]
|
||||
}
|
||||
|
||||
80
common/net/network.pb.go
Normal file
80
common/net/network.pb.go
Normal file
@@ -0,0 +1,80 @@
|
||||
// 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
|
||||
Network_RawTCP Network = 1
|
||||
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,
|
||||
}
|
||||
19
common/net/network.proto
Normal file
19
common/net/network.proto
Normal file
@@ -0,0 +1,19 @@
|
||||
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;
|
||||
RawTCP = 1;
|
||||
TCP = 2;
|
||||
UDP = 3;
|
||||
KCP = 4;
|
||||
WebSocket = 5;
|
||||
}
|
||||
|
||||
message NetworkList {
|
||||
repeated Network network = 1;
|
||||
}
|
||||
@@ -5,14 +5,23 @@ package net
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/collect"
|
||||
"v2ray.com/core/common/collect"
|
||||
)
|
||||
|
||||
func (this *Network) UnmarshalJSON(data []byte) error {
|
||||
var str string
|
||||
if err := json.Unmarshal(data, &str); err != nil {
|
||||
return err
|
||||
}
|
||||
*this = ParseNetwork(str)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *NetworkList) UnmarshalJSON(data []byte) error {
|
||||
var strlist collect.StringList
|
||||
if err := json.Unmarshal(data, &strlist); err != nil {
|
||||
return err
|
||||
}
|
||||
*this = NewNetworkList(strlist)
|
||||
*this = *NewNetworkList(strlist)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,18 +6,27 @@ import (
|
||||
"encoding/json"
|
||||
"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 TestStringNetwork(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var network Network
|
||||
err := json.Unmarshal([]byte(`"tcp"`), &network)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Bool(network == Network_TCP).IsTrue()
|
||||
}
|
||||
|
||||
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()
|
||||
assert.Bool(list.HasNetwork(ParseNetwork("tcp"))).IsTrue()
|
||||
assert.Bool(list.HasNetwork(ParseNetwork("udp"))).IsFalse()
|
||||
}
|
||||
|
||||
func TestStringNetworkList(t *testing.T) {
|
||||
@@ -26,8 +35,8 @@ func TestStringNetworkList(t *testing.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()
|
||||
assert.Bool(list.HasNetwork(ParseNetwork("tcp"))).IsTrue()
|
||||
assert.Bool(list.HasNetwork(ParseNetwork("udp"))).IsFalse()
|
||||
}
|
||||
|
||||
func TestInvalidNetworkJson(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/serial"
|
||||
"v2ray.com/core/common/serial"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,8 +23,8 @@ func PortFromBytes(port []byte) Port {
|
||||
|
||||
// PortFromInt converts an integer to a Port.
|
||||
// @error when the integer is not positive or larger then 65535
|
||||
func PortFromInt(v int) (Port, error) {
|
||||
if v <= 0 || v > 65535 {
|
||||
func PortFromInt(v uint32) (Port, error) {
|
||||
if v > 65535 {
|
||||
return Port(0), ErrInvalidPortRange
|
||||
}
|
||||
return Port(v), nil
|
||||
@@ -33,11 +33,11 @@ func PortFromInt(v int) (Port, error) {
|
||||
// PortFromString converts a string to a Port.
|
||||
// @error when the string is not an integer or the integral value is a not a valid Port.
|
||||
func PortFromString(s string) (Port, error) {
|
||||
v, err := strconv.Atoi(s)
|
||||
v, err := strconv.ParseUint(s, 10, 32)
|
||||
if err != nil {
|
||||
return Port(0), ErrInvalidPortRange
|
||||
}
|
||||
return PortFromInt(v)
|
||||
return PortFromInt(uint32(v))
|
||||
}
|
||||
|
||||
// Value return the correspoding uint16 value of this Port.
|
||||
@@ -55,13 +55,15 @@ func (this Port) String() string {
|
||||
return serial.Uint16ToString(this.Value())
|
||||
}
|
||||
|
||||
// PortRange represents a range of ports.
|
||||
type PortRange struct {
|
||||
From Port
|
||||
To Port
|
||||
func (this PortRange) FromPort() Port {
|
||||
return Port(this.From)
|
||||
}
|
||||
|
||||
func (this PortRange) ToPort() Port {
|
||||
return Port(this.To)
|
||||
}
|
||||
|
||||
// Contains returns true if the given port is within the range of this PortRange.
|
||||
func (this PortRange) Contains(port Port) bool {
|
||||
return this.From <= port && port <= this.To
|
||||
return this.FromPort() <= port && port <= this.ToPort()
|
||||
}
|
||||
|
||||
44
common/net/port.pb.go
Normal file
44
common/net/port.pb.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: v2ray.com/core/common/net/port.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
|
||||
|
||||
// PortRange represents a range of ports.
|
||||
type PortRange struct {
|
||||
From uint32 `protobuf:"varint,1,opt,name=From" json:"From,omitempty"`
|
||||
To uint32 `protobuf:"varint,2,opt,name=To" json:"To,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PortRange) Reset() { *m = PortRange{} }
|
||||
func (m *PortRange) String() string { return proto.CompactTextString(m) }
|
||||
func (*PortRange) ProtoMessage() {}
|
||||
func (*PortRange) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*PortRange)(nil), "v2ray.core.common.net.PortRange")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/common/net/port.proto", fileDescriptor3) }
|
||||
|
||||
var fileDescriptor3 = []byte{
|
||||
// 144 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x29, 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, 0x2f, 0xc8, 0x2f, 0x2a, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
|
||||
0x17, 0x12, 0x85, 0xa9, 0x2a, 0x4a, 0xd5, 0x83, 0xa8, 0xd0, 0xcb, 0x4b, 0x2d, 0x51, 0xd2, 0xe7,
|
||||
0xe2, 0x0c, 0xc8, 0x2f, 0x2a, 0x09, 0x4a, 0xcc, 0x4b, 0x4f, 0x15, 0x12, 0xe2, 0x62, 0x71, 0x2b,
|
||||
0xca, 0xcf, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0d, 0x02, 0xb3, 0x85, 0xf8, 0xb8, 0x98, 0x42,
|
||||
0xf2, 0x25, 0x98, 0xc0, 0x22, 0x4c, 0x21, 0xf9, 0x4e, 0xda, 0x5c, 0x92, 0xc9, 0xf9, 0xb9, 0x7a,
|
||||
0x58, 0x4d, 0x73, 0x02, 0x9b, 0x15, 0x00, 0xb2, 0x2f, 0x8a, 0x39, 0x2f, 0xb5, 0x24, 0x89, 0x0d,
|
||||
0x6c, 0xb7, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xfc, 0xe5, 0xb2, 0xd0, 0xa3, 0x00, 0x00, 0x00,
|
||||
}
|
||||
12
common/net/port.proto
Normal file
12
common/net/port.proto
Normal file
@@ -0,0 +1,12 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.common.net;
|
||||
option go_package = "net";
|
||||
option java_package = "com.v2ray.core.common.net";
|
||||
option java_outer_classname = "PortProto";
|
||||
|
||||
// PortRange represents a range of ports.
|
||||
message PortRange {
|
||||
uint32 From = 1;
|
||||
uint32 To = 2;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// +build json
|
||||
|
||||
package net
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
)
|
||||
|
||||
func parseIntPort(data []byte) (Port, error) {
|
||||
var intPort int
|
||||
err := json.Unmarshal(data, &intPort)
|
||||
if err != nil {
|
||||
return Port(0), err
|
||||
}
|
||||
return PortFromInt(intPort)
|
||||
}
|
||||
|
||||
func parseStringPort(data []byte) (Port, Port, error) {
|
||||
var s string
|
||||
err := json.Unmarshal(data, &s)
|
||||
if err != nil {
|
||||
return Port(0), Port(0), err
|
||||
}
|
||||
pair := strings.SplitN(s, "-", 2)
|
||||
if len(pair) == 0 {
|
||||
return Port(0), Port(0), ErrInvalidPortRange
|
||||
}
|
||||
if len(pair) == 1 {
|
||||
port, err := PortFromString(pair[0])
|
||||
return port, port, err
|
||||
}
|
||||
|
||||
fromPort, err := PortFromString(pair[0])
|
||||
if err != nil {
|
||||
return Port(0), Port(0), err
|
||||
}
|
||||
toPort, err := PortFromString(pair[1])
|
||||
if err != nil {
|
||||
return Port(0), Port(0), err
|
||||
}
|
||||
return fromPort, toPort, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||
func (this *PortRange) UnmarshalJSON(data []byte) error {
|
||||
port, err := parseIntPort(data)
|
||||
if err == nil {
|
||||
this.From = port
|
||||
this.To = port
|
||||
return nil
|
||||
}
|
||||
|
||||
from, to, err := parseStringPort(data)
|
||||
if err == nil {
|
||||
this.From = from
|
||||
this.To = to
|
||||
if this.From > this.To {
|
||||
log.Error("Invalid port range ", this.From, " -> ", this.To)
|
||||
return ErrInvalidPortRange
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Error("Invalid port range: ", string(data))
|
||||
return ErrInvalidPortRange
|
||||
}
|
||||
@@ -1,72 +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 TestIntPort(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("1234"), &portRange)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
assert.Uint16(portRange.From.Value()).Equals(uint16(1234))
|
||||
assert.Uint16(portRange.To.Value()).Equals(uint16(1234))
|
||||
}
|
||||
|
||||
func TestOverRangeIntPort(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("70000"), &portRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("-1"), &portRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
}
|
||||
|
||||
func TestSingleStringPort(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("\"1234\""), &portRange)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
assert.Uint16(portRange.From.Value()).Equals(uint16(1234))
|
||||
assert.Uint16(portRange.To.Value()).Equals(uint16(1234))
|
||||
}
|
||||
|
||||
func TestStringPairPort(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("\"1234-5678\""), &portRange)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
assert.Uint16(portRange.From.Value()).Equals(uint16(1234))
|
||||
assert.Uint16(portRange.To.Value()).Equals(uint16(5678))
|
||||
}
|
||||
|
||||
func TestOverRangeStringPort(t *testing.T) {
|
||||
assert := assert.On(t)
|
||||
|
||||
var portRange PortRange
|
||||
err := json.Unmarshal([]byte("\"65536\""), &portRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("\"70000-80000\""), &portRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("\"1-90000\""), &portRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
|
||||
err = json.Unmarshal([]byte("\"700-600\""), &portRange)
|
||||
assert.Error(err).Equals(ErrInvalidPortRange)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user