Compare commits

..

167 Commits

Author SHA1 Message Date
Darien Raymond
8dbb45bf06 remove test log 2016-11-22 00:54:40 +01:00
Darien Raymond
e0116d3957 fix http read 2016-11-22 00:52:26 +01:00
Darien Raymond
13b1bf09cf more log 2016-11-22 00:42:31 +01:00
Darien Raymond
de414de7a2 test log 2016-11-22 00:36:47 +01:00
Darien Raymond
dc0e9aa9b3 output bytes instead of string 2016-11-22 00:25:00 +01:00
Darien Raymond
90504fc077 better error handling 2016-11-22 00:20:06 +01:00
Darien Raymond
85da0dae28 fix printf 2016-11-22 00:19:51 +01:00
Darien Raymond
6804d8f73a better handling error from Pipe() 2016-11-22 00:17:49 +01:00
Darien Raymond
a9946a2dc1 don't close writing in ss test 2016-11-22 00:00:49 +01:00
Darien Raymond
85f9e39416 also resize value when error 2016-11-22 00:00:27 +01:00
Darien Raymond
36cc6f5ef2 remove unused code 2016-11-21 23:27:32 +01:00
Darien Raymond
bc822985ab shadowsocks log 2016-11-21 23:06:26 +01:00
Darien Raymond
15cb543abb release memory in kcp connection 2016-11-21 22:41:12 +01:00
Darien Raymond
70c75038a2 small buffer 2016-11-21 22:08:34 +01:00
Darien Raymond
c041740940 remove ErrMissingApplication 2016-11-21 21:13:01 +01:00
Darien Raymond
55be94f8e3 Update version 2016-11-20 22:09:32 +01:00
Darien Raymond
30cd9e929d add exponential backoff as retry logic 2016-11-20 21:47:51 +01:00
Darien Raymond
56fb8c478c remove unused code 2016-11-20 11:00:59 +01:00
Darien Raymond
6c441e2a5f format log 2016-11-20 01:43:08 +01:00
Darien Raymond
d6086e0e9b remove buggy test case 2016-11-19 22:54:42 +01:00
Darien Raymond
84740b676a handle empty payload 2016-11-19 22:40:14 +01:00
Darien Raymond
f64c79e239 log 2016-11-19 22:40:06 +01:00
Darien Raymond
1bbbb6e3cd release payload after writting 2016-11-19 22:39:18 +01:00
Darien Raymond
def8a19a7e small fixes 2016-11-19 22:38:50 +01:00
Darien Raymond
1169476e69 return correct number of bytes written 2016-11-19 22:38:24 +01:00
Darien Raymond
18cd10be2b revert buffer api change 2016-11-19 21:13:00 +01:00
Darien Raymond
87a8f7a953 fix chan writer 2016-11-19 21:12:52 +01:00
Darien Raymond
c884d04c7b buffer api 2016-11-19 14:38:35 +01:00
Darien Raymond
ecd0cf2fe2 fix proxy settings in vmess outbound 2016-11-19 14:38:28 +01:00
Darien Raymond
2078f29142 refine error message 2016-11-19 14:38:13 +01:00
Darien Raymond
26aa48d4f9 fix shadowsocks ota 2016-11-19 10:57:00 +01:00
Darien Raymond
5a32cd8602 remove large buffer 2016-11-19 01:50:09 +01:00
Darien Raymond
ac2f62b239 reduce memory footprint in kcp 2016-11-19 01:49:54 +01:00
Darien Raymond
ed780951aa save some goroutines 2016-11-19 01:48:38 +01:00
Darien Raymond
65a49e7fa0 small fixes 2016-11-19 00:37:11 +01:00
Darien Raymond
292176c57f simplify udp payload queue 2016-11-19 00:34:30 +01:00
Darien Raymond
1a1383c2ea simplify random 2016-11-18 21:34:42 +01:00
Darien Raymond
a14795e1e6 optimize udp hub 2016-11-18 21:30:03 +01:00
Darien Raymond
4ee758c4d2 simplify kcp logic 2016-11-18 16:19:13 +01:00
Darien Raymond
2a2b0242cb gofmt 2016-11-18 15:07:05 +01:00
Darien Raymond
4d51990c66 fix coverage 2016-11-18 00:31:59 +01:00
Darien Raymond
7632618584 fix temp file generation 2016-11-18 00:01:37 +01:00
Darien Raymond
03d8c33fd1 tag for default inbound and outbound 2016-11-17 23:23:46 +01:00
Darien Raymond
ad3f450bce fix usage of io.EOF 2016-11-17 23:21:44 +01:00
Darien Raymond
192def75a1 update service def 2016-11-14 12:53:20 +01:00
Darien Raymond
3a51157929 fix allow passive connection 2016-11-13 23:08:32 +01:00
Darien Raymond
e72f8a26c8 min timeout 2016-11-13 22:29:31 +01:00
Darien Raymond
0cd9f5165f update kcp sending worker 2016-11-13 22:27:58 +01:00
Darien Raymond
2115089d67 Update version 2016-11-13 21:31:17 +01:00
Darien Raymond
fc81b0aae2 config for inbound tag routing 2016-11-13 21:23:34 +01:00
Darien Raymond
b49f76cd1c fix tcp reading 2016-11-13 21:05:40 +01:00
Darien Raymond
9471b5b066 refine dispatcher 2016-11-13 14:33:00 +01:00
Darien Raymond
5dc05d6352 allow outbound to be proxied 2016-11-10 23:41:28 +01:00
Darien Raymond
e30f466424 update deploy key 2016-11-09 21:58:49 +01:00
Darien Raymond
2e0d54fd4c fix routing config on source IP 2016-11-09 10:56:15 +01:00
Darien Raymond
d343cb1ee6 proxy connection 2016-11-09 00:17:09 +01:00
Darien Raymond
7a09fcdc2f increase kcp ack frequency 2016-11-08 00:35:14 +01:00
Darien Raymond
b0d009664a Fix HTTP serialization 2016-11-07 10:47:30 +01:00
Darien Raymond
3d2431d21c update test data 2016-11-07 10:38:43 +01:00
Darien Raymond
d04e145442 Update version 2016-11-06 21:05:19 +01:00
Darien Raymond
d75cb28413 fix tcp encoding 2016-11-06 21:04:56 +01:00
Darien Raymond
9f68062d48 refine http header parsing 2016-11-06 15:48:25 +01:00
Darien Raymond
d70b997d84 test case for shadowsocks UDP 2016-11-06 14:32:04 +01:00
Darien Raymond
dc0cbce6e1 optimize pickString 2016-11-06 14:04:44 +01:00
Darien Raymond
edc5bbbb72 add more default headers 2016-11-06 13:55:06 +01:00
Darien Raymond
66e8090d3a update http header 2016-11-06 13:38:32 +01:00
Darien Raymond
805bbe5fe4 default user agent strings 2016-11-06 00:42:54 +01:00
Darien Raymond
31be091a55 simplify http header parsing 2016-11-05 15:14:55 +01:00
Darien Raymond
f108633e2e ssr compatibility 2016-11-05 01:50:51 +01:00
Darien Raymond
d2263a452d update http header json config 2016-11-05 01:28:15 +01:00
Darien Raymond
dfc03ff939 support noop connection auth 2016-11-05 01:15:32 +01:00
Darien Raymond
13dde1799d comments 2016-11-05 01:01:46 +01:00
Darien Raymond
c84629c374 add shadowsocks in json config 2016-11-05 01:01:30 +01:00
Darien Raymond
817cc8d82e fix shadowsocks conf 2016-11-05 01:01:07 +01:00
Darien Raymond
13ab2622c5 shadowsocks test 2016-11-05 01:00:54 +01:00
Darien Raymond
0727aa0da9 simplify imports 2016-11-05 01:00:20 +01:00
Darien Raymond
3a15f799c2 prevent deadlock in shadowsocks 2016-11-05 01:00:09 +01:00
Darien Raymond
bae0de7d95 test case for http auth 2016-11-04 21:59:19 +01:00
Darien Raymond
80312627c4 fix typo 2016-11-04 10:49:43 +01:00
Darien Raymond
3d167a6855 json config for http header 2016-11-04 10:49:18 +01:00
Darien Raymond
010f34c76c allow single side auth 2016-11-03 23:14:27 +01:00
Darien Raymond
0747203132 refine http header 2016-11-02 22:26:21 +01:00
Darien Raymond
1600a59254 enable tcp for shadowsocks server 2016-11-02 22:19:01 +01:00
Darien Raymond
c5a92e00ef dont reuse shadowsock connections 2016-11-02 22:18:25 +01:00
Darien Raymond
68b85cce60 remove unused code 2016-11-02 16:42:02 +01:00
Darien Raymond
9d2407f4e4 fix test break 2016-11-02 16:41:02 +01:00
Darien Raymond
cdb0debcb0 register shadowsocks client factory 2016-11-02 16:38:09 +01:00
Darien Raymond
5f3f173b5e shadowsocks client factory 2016-11-02 16:33:04 +01:00
Darien Raymond
35aa16d40d refine shadowsocks user 2016-11-02 16:22:29 +01:00
Darien Raymond
de4836c720 refine ota settings in conf 2016-11-02 16:21:20 +01:00
Darien Raymond
63d3c9fa30 typo 2016-11-02 16:18:29 +01:00
Darien Raymond
687e008c9a refine shadowsocks ota settings 2016-11-02 16:17:57 +01:00
Darien Raymond
43dacc3936 remove small buffer pool 2016-11-01 12:37:35 +01:00
Darien Raymond
aabb9137e1 remove unused code 2016-11-01 12:34:07 +01:00
Darien Raymond
33d2513e3c reduce memory allocation in kcp 2016-11-01 12:07:20 +01:00
Darien Raymond
5b58066345 use local buffer in UDP hub 2016-11-01 11:46:34 +01:00
Darien Raymond
d3f323e24b response factory 2016-11-01 00:42:55 +01:00
Darien Raymond
187688cacb fix type def 2016-11-01 00:42:44 +01:00
Darien Raymond
72339a3509 fix TCP conn reuse with tls 2016-11-01 00:41:46 +01:00
Darien Raymond
ac3b91a877 http authenticator 2016-10-31 22:26:46 +01:00
Darien Raymond
5e1c6fe816 bug fix 2016-10-31 16:46:47 +01:00
Darien Raymond
a54c39b4ac config for shadowsocks 2016-10-31 16:46:15 +01:00
Darien Raymond
c221802963 shadowsocks client 2016-10-31 16:35:18 +01:00
Darien Raymond
be4f3d0772 refine shadowsocks server 2016-10-31 15:24:28 +01:00
Darien Raymond
fbb44e7e02 fix string checking logic 2016-10-24 16:59:43 +02:00
Darien Raymond
369256c82f include user when dispatch requests in VMess. 2016-10-24 16:57:16 +02:00
Darien Raymond
531be77a59 remove test case depending on external resources 2016-10-24 16:49:41 +02:00
Darien Raymond
97dc7b30de remove test cases depending on external resources 2016-10-24 16:48:16 +02:00
Darien Raymond
360c222c1c try again to skip coverage on release 2016-10-24 16:45:02 +02:00
Darien Raymond
1fb9a911cd workaround travis issue 2016-10-24 16:42:28 +02:00
Darien Raymond
6006fd9ca7 Update version 2016-10-24 15:09:24 +02:00
Darien Raymond
59fa064cae default log settings 2016-10-24 15:08:06 +02:00
Darien Raymond
3373e62193 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2016-10-24 15:04:23 +02:00
Darien Raymond
2c2c569c77 Update to Go 1.7.3 2016-10-24 14:13:21 +02:00
Darien Raymond
687ae6c50e chunk writer 2016-10-21 00:33:23 +02:00
Darien Raymond
35ba8710e0 fix ip check in ipnet 2016-10-19 15:38:31 +02:00
Darien Raymond
a7ef82ffbc fix test break 2016-10-19 12:01:11 +02:00
Darien Raymond
ca980f5718 json conf for source session in router 2016-10-18 23:14:48 +02:00
Darien Raymond
aae99a8e98 use session in router 2016-10-18 23:01:39 +02:00
Darien Raymond
f37b04a690 per connection stream settings 2016-10-18 21:57:40 +02:00
Darien Raymond
e13c97d162 rename IP to CIDR in router 2016-10-18 16:42:22 +02:00
Darien Raymond
2af4b16913 remove string list 2016-10-18 16:10:50 +02:00
Darien Raymond
2320bc3304 remove unused code 2016-10-18 15:31:48 +02:00
Darien Raymond
751a105324 comments 2016-10-18 15:31:39 +02:00
Darien Raymond
b3bbd80674 fix json parser for IPv6 routing 2016-10-18 11:36:45 +02:00
Darien Raymond
4e80ed05d9 comments 2016-10-18 10:31:39 +02:00
Darien Raymond
426a58707f skip coverage for releases 2016-10-18 10:28:37 +02:00
Darien Raymond
9b4d9cf0e7 nil pointer 2016-10-18 10:04:15 +02:00
Darien Raymond
f049b3cc2b comments 2016-10-18 00:12:09 +02:00
Darien Raymond
b81d091fb8 comments 2016-10-18 00:09:49 +02:00
Darien Raymond
9bd8822668 unused proto 2016-10-18 00:09:41 +02:00
Darien Raymond
ad59e56925 default send through value 2016-10-18 00:02:41 +02:00
Darien Raymond
4a67587873 fix geoip 2016-10-17 16:35:18 +02:00
Darien Raymond
8b936bc816 fix release binary 2016-10-17 15:52:07 +02:00
Darien Raymond
9ae4611eac fix file name for openbsd 2016-10-17 15:23:45 +02:00
Darien Raymond
14996da74a Update version 2016-10-17 14:55:58 +02:00
Darien Raymond
7a14f646ee gofmt 2016-10-17 14:44:06 +02:00
Darien Raymond
67d597af95 openbsd release 2016-10-17 14:41:54 +02:00
Darien Raymond
5a311cbe08 json config parser 2016-10-17 14:35:13 +02:00
Darien Raymond
e866ff24a4 refine app settings in v2ray config 2016-10-16 16:04:30 +02:00
Darien Raymond
e33b7df34c remove use of any 2016-10-16 14:22:21 +02:00
Darien Raymond
5d9e6b0799 json reference 2016-10-16 00:46:30 +02:00
Darien Raymond
39939b00f0 outbound config 2016-10-16 00:46:08 +02:00
Darien Raymond
be4cfdf61c add tls 2016-10-16 00:45:35 +02:00
Darien Raymond
be026870f7 protogen update 2016-10-16 00:23:27 +02:00
Darien Raymond
348893a02a register protobuf config loader 2016-10-14 23:42:14 +02:00
Darien Raymond
35a0ed6fb4 config loader 2016-10-14 23:41:41 +02:00
Darien Raymond
84f660bbbc update main code 2016-10-14 23:41:17 +02:00
Darien Raymond
8ad04f911d all references 2016-10-14 23:41:06 +02:00
Darien Raymond
0a32345af9 protobuf for v2ray config 2016-10-14 22:21:45 +02:00
Darien Raymond
f87d7f36f5 check nil settings 2016-10-14 21:19:45 +02:00
Darien Raymond
f488a63d97 check nil config 2016-10-14 21:19:26 +02:00
Darien Raymond
b060bb3b94 refactor proxy config cache 2016-10-13 11:14:24 +02:00
Darien Raymond
d26ee5441e fix authenticator config 2016-10-12 22:43:17 +02:00
Darien Raymond
fc6a706166 refactor protos 2016-10-12 18:43:55 +02:00
Darien Raymond
c1f91567ad refactor shell 2016-10-12 16:46:02 +02:00
Darien Raymond
22ef12a456 simplify router 2016-10-12 16:11:13 +02:00
Darien Raymond
63f3108737 protobuf for router 2016-10-11 23:02:44 +02:00
Darien Raymond
ab3173039b increase ping interval 2016-10-11 21:21:06 +02:00
Darien Raymond
b5910dccae simplify fast resend 2016-10-11 13:17:57 +02:00
Darien Raymond
f8ad1f4a3e update predicate syntax 2016-10-11 12:44:17 +02:00
Darien Raymond
da9f1a8013 predicate.Not 2016-10-11 12:30:53 +02:00
Darien Raymond
f3a83c57ab optimize ping and updater logic 2016-10-11 12:24:19 +02:00
Darien Raymond
78f87c4f60 test case for cmd only segment 2016-10-11 11:44:30 +02:00
Darien Raymond
e023859ef0 stop data updating thread when there is no data 2016-10-10 16:50:54 +02:00
Darien Raymond
5f920a9e94 protobuf for log config 2016-10-03 22:07:28 +02:00
Darien Raymond
bd9b7c586e remove unnecessary code in main 2016-10-03 21:37:09 +02:00
284 changed files with 7690 additions and 12908 deletions

View File

@@ -1,39 +1,34 @@
language: go
go:
- 1.7.1
- 1.7.3
go_import_path: v2ray.com/core
git:
depth: 5
script:
- go test -tags json v2ray.com/core/...
- go test -tags json v2ray.com/core/...
after_success:
- ./testing/coverage/coverall
- ./testing/coverage/coverall
before_deploy:
- rvm 1.9.3 do gem install mime-types -v 2.6.2
- "./tools/release/release-ci.sh"
- ./tools/release/release-ci.sh
- gem install octokit -v 4.3.0
deploy:
provider: releases
api_key:
secure: "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="
api_key:
secure: h7P6y7jHe0yALKgXb9HyPAlE6JPOB/BiScMlqsG6MUF0G29JrEjcDXh/jZm8HB82OfUG3zPBtr5m0P3LUoM60EQQ96/yE9KKrhEBeyF+E9CAOUHx7Ar4XDR7dG7/Wv+q3ZRFl+4CB5f7xbt9qlobqXkeffngeu9RNWngqVvbyTWIZclx7NYl5haf/hhqGcX2OPKQQfjvOsnP+uLmqiRJBbaYQMzPmvjaQJ9cB6Z11ctJqunk3bN89nV86uaHLqmz8nfk3/J7RjdeT0mqgRYVwfMavZifGPISlgsZd7N0PqiiWB7gZqzjbiSCur+PtnVScYfTlfNoRP+XJtVx3OFnepffSvyE6zOP20MEINAMOgME68Zzkaab8JnDVwj0eTsPNEDpK+E+RUZ1IkaAvVZ19L0qNYwO6bP8koUI4cFDI45srcx0o5xC7Hzz1eaSm5ZJZ3iwwzFZE2vFm83pcQilopG0E7gTYyB+fk0x6sca5MY1PhHAByvBbvYhsCBV4x4o0N1lD1V3QXhvljJL4qieFybwg8g0hdUNeSrm2+NxPqKpEHUQWQFGsl0OGMy2Ji6u/NG5tSvfWKUUsXpkueyutvfTb9D94Xk4s1eNGMG+BHFIGHRTZzX6XXB7/j3zObWApD3h8SIbXjfL0mLaKaBeMyLwf2tlsKTgzwEjvIzcNfQ=
file:
- "$GOPATH/bin/v2ray-macos.zip"
- "$GOPATH/bin/v2ray-windows-64.zip"
- "$GOPATH/bin/v2ray-windows-32.zip"
- "$GOPATH/bin/v2ray-linux-64.zip"
- "$GOPATH/bin/v2ray-linux-32.zip"
- "$GOPATH/bin/v2ray-linux-arm.zip"
- "$GOPATH/bin/v2ray-linux-arm64.zip"
- "$GOPATH/bin/v2ray-linux-mips64.zip"
- "$GOPATH/bin/v2ray-freebsd-64.zip"
- "$GOPATH/bin/v2ray-freebsd-32.zip"
- "$GOPATH/bin/metadata.txt"
- $GOPATH/bin/v2ray-macos.zip
- $GOPATH/bin/v2ray-windows-64.zip
- $GOPATH/bin/v2ray-windows-32.zip
- $GOPATH/bin/v2ray-linux-64.zip
- $GOPATH/bin/v2ray-linux-32.zip
- $GOPATH/bin/v2ray-linux-arm.zip
- $GOPATH/bin/v2ray-linux-arm64.zip
- $GOPATH/bin/v2ray-linux-mips64.zip
- $GOPATH/bin/v2ray-freebsd-64.zip
- $GOPATH/bin/v2ray-freebsd-32.zip
- $GOPATH/bin/v2ray-openbsd-64.zip
- $GOPATH/bin/v2ray-openbsd-32.zip
- $GOPATH/bin/metadata.txt
skip_cleanup: true
on:
tags: true

28
all.go Normal file
View File

@@ -0,0 +1,28 @@
package core
import (
// The following are necessary as they register handlers in their init functions.
_ "v2ray.com/core/app/dns"
_ "v2ray.com/core/app/proxy"
_ "v2ray.com/core/app/router"
_ "v2ray.com/core/proxy/blackhole"
_ "v2ray.com/core/proxy/dokodemo"
_ "v2ray.com/core/proxy/freedom"
_ "v2ray.com/core/proxy/http"
_ "v2ray.com/core/proxy/shadowsocks"
_ "v2ray.com/core/proxy/socks"
_ "v2ray.com/core/proxy/vmess/inbound"
_ "v2ray.com/core/proxy/vmess/outbound"
_ "v2ray.com/core/transport/internet/kcp"
_ "v2ray.com/core/transport/internet/tcp"
_ "v2ray.com/core/transport/internet/tls"
_ "v2ray.com/core/transport/internet/udp"
_ "v2ray.com/core/transport/internet/ws"
_ "v2ray.com/core/transport/internet/authenticators/http"
_ "v2ray.com/core/transport/internet/authenticators/noop"
_ "v2ray.com/core/transport/internet/authenticators/srtp"
_ "v2ray.com/core/transport/internet/authenticators/utp"
)

View File

@@ -12,5 +12,5 @@ const (
// PacketDispatcher dispatch a packet and possibly further network payload to its destination.
type PacketDispatcher interface {
DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay
DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay
}

View File

@@ -1,6 +1,7 @@
package impl
import (
"errors"
"v2ray.com/core/app"
"v2ray.com/core/app/proxyman"
"v2ray.com/core/app/router"
@@ -13,7 +14,7 @@ import (
type DefaultDispatcher struct {
ohm proxyman.OutboundHandlerManager
router router.Router
router *router.Router
}
func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
@@ -27,13 +28,12 @@ func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
// 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.")
return app.ErrMissingApplication
return errors.New("DefaultDispatcher: OutboundHandlerManager is not found in the space.")
}
this.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
if space.HasApp(router.APP_ID) {
this.router = space.GetApp(router.APP_ID).(router.Router)
this.router = space.GetApp(router.APP_ID).(*router.Router)
}
return nil
@@ -43,13 +43,13 @@ func (this *DefaultDispatcher) Release() {
}
func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay {
func (this *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
direct := ray.NewRay()
dispatcher := this.ohm.GetDefaultHandler()
destination := session.Destination
if this.router != nil {
if tag, err := this.router.TakeDetour(destination); err == nil {
if tag, err := this.router.TakeDetour(session); err == nil {
if handler := this.ohm.GetHandler(tag); handler != nil {
log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].")
dispatcher = handler
@@ -61,7 +61,7 @@ func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta
}
}
if meta.AllowPassiveConnection {
if session.Inbound != nil && session.Inbound.AllowPassiveConnection {
go dispatcher.Dispatch(destination, alloc.NewLocalBuffer(32).Clear(), direct)
} else {
go this.FilterPacketAndDispatch(destination, direct, dispatcher)

View File

@@ -30,7 +30,7 @@ func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic
}
}
func (this *TestPacketDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, session *proxy.SessionInfo) ray.InboundRay {
func (this *TestPacketDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay {
traffic := ray.NewRay()
this.Destination <- session.Destination
go this.Handler(session.Destination, traffic)

View File

@@ -8,8 +8,8 @@ import (
func (this *Config) GetInternalHosts() map[string]net.IP {
hosts := make(map[string]net.IP)
for domain, addressPB := range this.GetHosts() {
address := addressPB.AsAddress()
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

View File

@@ -31,8 +31,11 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Config struct {
NameServers []*v2ray_core_common_net2.DestinationPB `protobuf:"bytes,1,rep,name=NameServers,json=nameServers" json:"NameServers,omitempty"`
Hosts map[string]*v2ray_core_common_net.AddressPB `protobuf:"bytes,2,rep,name=Hosts,json=hosts" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
// Nameservers used by this DNS. Only traditional UDP servers are support at the moment.
// A special value 'localhost' as a domain address can be set to use DNS on local system.
NameServers []*v2ray_core_common_net2.Endpoint `protobuf:"bytes,1,rep,name=NameServers" json:"NameServers,omitempty"`
// Static hosts. Domain to IP.
Hosts map[string]*v2ray_core_common_net.IPOrDomain `protobuf:"bytes,2,rep,name=Hosts" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (m *Config) Reset() { *m = Config{} }
@@ -40,14 +43,14 @@ 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.DestinationPB {
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.AddressPB {
func (m *Config) GetHosts() map[string]*v2ray_core_common_net.IPOrDomain {
if m != nil {
return m.Hosts
}
@@ -61,22 +64,22 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/app/dns/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 270 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x90, 0xcb, 0x4a, 0xc4, 0x30,
0x14, 0x86, 0x49, 0x4b, 0x07, 0x4c, 0x37, 0x92, 0x85, 0x94, 0xae, 0x8a, 0x17, 0x2c, 0x0a, 0x09,
0x54, 0x10, 0xd1, 0x95, 0xf5, 0x82, 0x2b, 0x29, 0x75, 0x37, 0xbb, 0xd8, 0x1c, 0xb5, 0x68, 0x4f,
0x4a, 0x12, 0x0b, 0x7d, 0x64, 0xdf, 0x42, 0xda, 0x20, 0x15, 0x9d, 0xd9, 0x1d, 0xc2, 0xf7, 0x5f,
0xf2, 0xd3, 0x83, 0xa1, 0x30, 0x72, 0xe4, 0x8d, 0xee, 0x44, 0xa3, 0x0d, 0x08, 0xd9, 0xf7, 0x42,
0xa1, 0x15, 0x8d, 0xc6, 0x97, 0xf6, 0x95, 0xf7, 0x46, 0x3b, 0xcd, 0xd8, 0x0f, 0x64, 0x80, 0xcb,
0xbe, 0xe7, 0x0a, 0x6d, 0x7a, 0xfc, 0x47, 0xd8, 0xe8, 0xae, 0xd3, 0x28, 0x10, 0x9c, 0x90, 0x4a,
0x19, 0xb0, 0xd6, 0x8b, 0xd3, 0xd3, 0xed, 0xa0, 0x02, 0xeb, 0x5a, 0x94, 0xae, 0xd5, 0xe8, 0xe1,
0xfd, 0x2f, 0x42, 0x57, 0x37, 0x73, 0x34, 0xbb, 0xa7, 0xf1, 0xa3, 0xec, 0xe0, 0x09, 0xcc, 0x00,
0xc6, 0x26, 0x24, 0x0b, 0xf3, 0xb8, 0x38, 0xe4, 0xbf, 0xaa, 0x78, 0x27, 0x8e, 0xe0, 0xf8, 0xed,
0xe2, 0x54, 0x95, 0x75, 0x8c, 0x8b, 0x90, 0x5d, 0xd1, 0xe8, 0x41, 0x5b, 0x67, 0x93, 0x60, 0x76,
0x38, 0xe2, 0xff, 0x3f, 0xc3, 0x7d, 0x24, 0x9f, 0xb9, 0x3b, 0x74, 0x66, 0xac, 0xa3, 0xb7, 0xe9,
0x4e, 0xd7, 0x94, 0x2e, 0x8f, 0x6c, 0x97, 0x86, 0xef, 0x30, 0x26, 0x24, 0x23, 0xf9, 0x4e, 0x3d,
0x9d, 0xec, 0x9c, 0x46, 0x83, 0xfc, 0xf8, 0x84, 0x24, 0xc8, 0x48, 0x1e, 0x17, 0xd9, 0x96, 0x7a,
0xd7, 0x7e, 0x91, 0xaa, 0xac, 0x3d, 0x7e, 0x19, 0x5c, 0x90, 0xf2, 0x84, 0xee, 0x35, 0xba, 0xdb,
0x50, 0xa7, 0x8c, 0x7d, 0x9f, 0x6a, 0x9a, 0x64, 0x1d, 0x2a, 0xb4, 0xcf, 0xab, 0x79, 0x9e, 0xb3,
0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x17, 0x9a, 0x1d, 0xee, 0xaf, 0x01, 0x00, 0x00,
// 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,
}

View File

@@ -9,6 +9,10 @@ import "v2ray.com/core/common/net/address.proto";
import "v2ray.com/core/common/net/destination.proto";
message Config {
repeated v2ray.core.common.net.DestinationPB NameServers = 1;
map<string, v2ray.core.common.net.AddressPB> Hosts = 2;
// Nameservers used by this DNS. Only traditional UDP servers are support at the moment.
// A special value 'localhost' as a domain address can be set to use DNS on local system.
repeated v2ray.core.common.net.Endpoint NameServers = 1;
// Static hosts. Domain to IP.
map<string, v2ray.core.common.net.IPOrDomain> Hosts = 2;
}

View File

@@ -1,34 +0,0 @@
// +build json
package dns
import (
"encoding/json"
v2net "v2ray.com/core/common/net"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Servers []*v2net.AddressPB `json:"servers"`
Hosts map[string]*v2net.AddressPB `json:"hosts"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
return err
}
this.NameServers = make([]*v2net.DestinationPB, len(jsonConfig.Servers))
for idx, server := range jsonConfig.Servers {
this.NameServers[idx] = &v2net.DestinationPB{
Network: v2net.Network_UDP,
Address: server,
Port: 53,
}
}
if jsonConfig.Hosts != nil {
this.Hosts = jsonConfig.Hosts
}
return nil
}

View File

@@ -50,11 +50,9 @@ type UDPNameServer struct {
func NewUDPNameServer(address v2net.Destination, dispatcher dispatcher.PacketDispatcher) *UDPNameServer {
s := &UDPNameServer{
address: address,
requests: make(map[uint16]*PendingRequest),
udpServer: udp.NewUDPServer(&proxy.InboundHandlerMeta{
AllowPassiveConnection: false,
}, dispatcher),
address: address,
requests: make(map[uint16]*PendingRequest),
udpServer: udp.NewUDPServer(dispatcher),
}
return s
}

View File

@@ -1,12 +1,14 @@
package dns
import (
"errors"
"net"
"sync"
"time"
"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"
@@ -37,8 +39,7 @@ func NewCacheServer(space app.Space, config *Config) *CacheServer {
}
space.InitializeApplication(func() error {
if !space.HasApp(dispatcher.APP_ID) {
log.Error("DNS: Dispatcher is not found in the space.")
return app.ErrMissingApplication
return errors.New("DNS: Dispatcher is not found in the space.")
}
dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
@@ -111,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{})
}

View File

@@ -1,56 +0,0 @@
package dns_test
import (
"net"
"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"
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) {
assert := assert.On(t)
space := app.NewSpace()
outboundHandlerManager := proxyman.NewDefaultOutboundHandlerManager()
outboundHandlerManager.SetDefaultHandler(
freedom.NewFreedomConnection(
&freedom.Config{},
space,
&proxy.OutboundHandlerMeta{
Address: v2net.AnyIP,
StreamSettings: &internet.StreamConfig{
Network: v2net.Network_RawTCP,
},
}))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager)
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
domain := "local.v2ray.com"
server := NewCacheServer(space, &Config{
NameServers: []*v2net.DestinationPB{{
Network: v2net.Network_UDP,
Address: &v2net.AddressPB{
Address: &v2net.AddressPB_Ip{
Ip: []byte{8, 8, 8, 8},
},
},
Port: 53,
}},
})
space.BindApp(APP_ID, server)
space.Initialize()
ips := server.Get(domain)
assert.Int(len(ips)).Equals(1)
assert.IP(ips[0].To4()).Equals(net.IP([]byte{127, 0, 0, 1}))
}

135
app/proxy/proxy.go Normal file
View File

@@ -0,0 +1,135 @@
package proxy
import (
"errors"
"io"
"net"
"time"
"v2ray.com/core/app"
"v2ray.com/core/app/proxyman"
v2io "v2ray.com/core/common/io"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/transport/internet"
"v2ray.com/core/transport/ray"
)
const (
APP_ID = 7
)
type OutboundProxy struct {
outboundManager proxyman.OutboundHandlerManager
}
func NewOutboundProxy(space app.Space) *OutboundProxy {
proxy := new(OutboundProxy)
space.InitializeApplication(func() error {
if !space.HasApp(proxyman.APP_ID_OUTBOUND_MANAGER) {
return errors.New("Proxy: Outbound handler manager not found.")
}
proxy.outboundManager = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
return nil
})
return proxy
}
func (this *OutboundProxy) RegisterDialer() {
internet.ProxyDialer = this.Dial
}
func (this *OutboundProxy) Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOptions) (internet.Connection, error) {
handler := this.outboundManager.GetHandler(options.Proxy.Tag)
if handler == nil {
log.Warning("Proxy: Failed to get outbound handler with tag: ", options.Proxy.Tag)
return internet.Dial(src, dest, internet.DialerOptions{
Stream: options.Stream,
})
}
log.Info("Proxy: Dialing to ", dest)
stream := ray.NewRay()
go handler.Dispatch(dest, nil, stream)
return NewProxyConnection(src, dest, stream), nil
}
func (this *OutboundProxy) Release() {
}
type ProxyConnection struct {
stream ray.Ray
closed bool
localAddr net.Addr
remoteAddr net.Addr
reader *v2io.ChanReader
writer *v2io.ChainWriter
}
func NewProxyConnection(src v2net.Address, dest v2net.Destination, stream ray.Ray) *ProxyConnection {
return &ProxyConnection{
stream: stream,
localAddr: &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
Port: 0,
},
remoteAddr: &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
Port: 0,
},
reader: v2io.NewChanReader(stream.InboundOutput()),
writer: v2io.NewChainWriter(stream.InboundInput()),
}
}
func (this *ProxyConnection) Read(b []byte) (int, error) {
if this.closed {
return 0, io.EOF
}
return this.reader.Read(b)
}
func (this *ProxyConnection) Write(b []byte) (int, error) {
if this.closed {
return 0, io.ErrClosedPipe
}
return this.writer.Write(b)
}
func (this *ProxyConnection) Close() error {
this.closed = true
this.stream.InboundInput().Close()
this.stream.InboundOutput().Release()
this.reader.Release()
this.writer.Release()
return nil
}
func (this *ProxyConnection) LocalAddr() net.Addr {
return this.localAddr
}
func (this *ProxyConnection) RemoteAddr() net.Addr {
return this.remoteAddr
}
func (this *ProxyConnection) SetDeadline(t time.Time) error {
return nil
}
func (this *ProxyConnection) SetReadDeadline(t time.Time) error {
return nil
}
func (this *ProxyConnection) SetWriteDeadline(t time.Time) error {
return nil
}
func (this *ProxyConnection) Reusable() bool {
return false
}
func (this *ProxyConnection) SetReusable(bool) {
}

68
app/proxy/proxy_test.go Normal file
View File

@@ -0,0 +1,68 @@
package proxy_test
import (
"testing"
"v2ray.com/core/app"
. "v2ray.com/core/app/proxy"
"v2ray.com/core/app/proxyman"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
"v2ray.com/core/proxy/freedom"
"v2ray.com/core/testing/assert"
"v2ray.com/core/testing/servers/tcp"
"v2ray.com/core/transport/internet"
)
func TestProxyDial(t *testing.T) {
assert := assert.On(t)
space := app.NewSpace()
outboundManager := proxyman.NewDefaultOutboundHandlerManager()
outboundManager.SetHandler("tag", freedom.NewFreedomConnection(&freedom.Config{}, space, &proxy.OutboundHandlerMeta{
Tag: "tag",
StreamSettings: &internet.StreamConfig{
Network: v2net.Network_RawTCP,
},
}))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundManager)
proxy := NewOutboundProxy(space)
space.BindApp(APP_ID, proxy)
assert.Error(space.Initialize()).IsNil()
xor := func(b []byte) []byte {
for idx, x := range b {
b[idx] = x ^ 'c'
}
return b
}
tcpServer := &tcp.Server{
MsgProcessor: xor,
}
dest, err := tcpServer.Start()
assert.Error(err).IsNil()
conn, err := proxy.Dial(v2net.LocalHostIP, dest, internet.DialerOptions{
Stream: &internet.StreamConfig{
Network: v2net.Network_RawTCP,
},
Proxy: &internet.ProxyConfig{
Tag: "tag",
},
})
assert.Error(err).IsNil()
_, err = conn.Write([]byte{'a', 'b', 'c', 'd'})
assert.Error(err).IsNil()
b := make([]byte, 10)
nBytes, err := conn.Read(b)
assert.Error(err).IsNil()
assert.Bytes(xor(b[:nBytes])).Equals([]byte{'a', 'b', 'c', 'd'})
conn.Close()
tcpServer.Close()
}

View File

@@ -1,4 +1,4 @@
package rules
package router
import (
"net"
@@ -6,10 +6,11 @@ import (
"strings"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
)
type Condition interface {
Apply(dest v2net.Destination) bool
Apply(session *proxy.SessionInfo) bool
}
type ConditionChan []Condition
@@ -24,9 +25,9 @@ func (this *ConditionChan) Add(cond Condition) *ConditionChan {
return this
}
func (this *ConditionChan) Apply(dest v2net.Destination) bool {
func (this *ConditionChan) Apply(session *proxy.SessionInfo) bool {
for _, cond := range *this {
if !cond.Apply(dest) {
if !cond.Apply(session) {
return false
}
}
@@ -49,9 +50,9 @@ func (this *AnyCondition) Add(cond Condition) *AnyCondition {
return this
}
func (this *AnyCondition) Apply(dest v2net.Destination) bool {
func (this *AnyCondition) Apply(session *proxy.SessionInfo) bool {
for _, cond := range *this {
if cond.Apply(dest) {
if cond.Apply(session) {
return true
}
}
@@ -72,7 +73,8 @@ func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
}
}
func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool {
func (this *PlainDomainMatcher) Apply(session *proxy.SessionInfo) bool {
dest := session.Destination
if !dest.Address.Family().IsDomain() {
return false
}
@@ -94,7 +96,8 @@ func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
}, nil
}
func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
func (this *RegexpDomainMatcher) Apply(session *proxy.SessionInfo) bool {
dest := session.Destination
if !dest.Address.Family().IsDomain() {
return false
}
@@ -103,20 +106,26 @@ func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
}
type CIDRMatcher struct {
cidr *net.IPNet
cidr *net.IPNet
onSource bool
}
func NewCIDRMatcher(ipnet string) (*CIDRMatcher, error) {
_, cidr, err := net.ParseCIDR(ipnet)
if err != nil {
return nil, err
func NewCIDRMatcher(ip []byte, mask uint32, onSource bool) (*CIDRMatcher, error) {
cidr := &net.IPNet{
IP: net.IP(ip),
Mask: net.CIDRMask(int(mask), len(ip)),
}
return &CIDRMatcher{
cidr: cidr,
cidr: cidr,
onSource: onSource,
}, nil
}
func (this *CIDRMatcher) Apply(dest v2net.Destination) bool {
func (this *CIDRMatcher) Apply(session *proxy.SessionInfo) bool {
dest := session.Destination
if this.onSource {
dest = session.Source
}
if !dest.Address.Family().Either(v2net.AddressFamilyIPv4, v2net.AddressFamilyIPv6) {
return false
}
@@ -124,16 +133,22 @@ func (this *CIDRMatcher) Apply(dest v2net.Destination) bool {
}
type IPv4Matcher struct {
ipv4net *v2net.IPNet
ipv4net *v2net.IPNet
onSource bool
}
func NewIPv4Matcher(ipnet *v2net.IPNet) *IPv4Matcher {
func NewIPv4Matcher(ipnet *v2net.IPNet, onSource bool) *IPv4Matcher {
return &IPv4Matcher{
ipv4net: ipnet,
ipv4net: ipnet,
onSource: onSource,
}
}
func (this *IPv4Matcher) Apply(dest v2net.Destination) bool {
func (this *IPv4Matcher) Apply(session *proxy.SessionInfo) bool {
dest := session.Destination
if this.onSource {
dest = session.Source
}
if !dest.Address.Family().Either(v2net.AddressFamilyIPv4) {
return false
}
@@ -150,8 +165,8 @@ func NewPortMatcher(portRange v2net.PortRange) *PortMatcher {
}
}
func (this *PortMatcher) Apply(dest v2net.Destination) bool {
return this.port.Contains(dest.Port)
func (this *PortMatcher) Apply(session *proxy.SessionInfo) bool {
return this.port.Contains(session.Destination.Port)
}
type NetworkMatcher struct {
@@ -164,6 +179,51 @@ func NewNetworkMatcher(network *v2net.NetworkList) *NetworkMatcher {
}
}
func (this *NetworkMatcher) Apply(dest v2net.Destination) bool {
return this.network.HasNetwork(dest.Network)
func (this *NetworkMatcher) Apply(session *proxy.SessionInfo) bool {
return this.network.HasNetwork(session.Destination.Network)
}
type UserMatcher struct {
user []string
}
func NewUserMatcher(users []string) *UserMatcher {
return &UserMatcher{
user: users,
}
}
func (this *UserMatcher) Apply(session *proxy.SessionInfo) bool {
if session.User == nil {
return false
}
for _, u := range this.user {
if u == session.User.Email {
return true
}
}
return false
}
type InboundTagMatcher struct {
tags []string
}
func NewInboundTagMatcher(tags []string) *InboundTagMatcher {
return &InboundTagMatcher{
tags: tags,
}
}
func (this *InboundTagMatcher) Apply(session *proxy.SessionInfo) bool {
if session.Inbound == nil || len(session.Inbound.Tag) == 0 {
return false
}
for _, t := range this.tags {
if t == session.Inbound.Tag {
return true
}
}
return false
}

View File

@@ -1,6 +1,126 @@
package router
type Config struct {
Strategy string
Settings interface{}
import (
"errors"
"net"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
)
type Rule struct {
Tag string
Condition Condition
}
func (this *Rule) Apply(session *proxy.SessionInfo) bool {
return this.Condition.Apply(session)
}
func (this *RoutingRule) BuildCondition() (Condition, error) {
conds := NewConditionChan()
if len(this.Domain) > 0 {
anyCond := NewAnyCondition()
for _, domain := range this.Domain {
if domain.Type == Domain_Plain {
anyCond.Add(NewPlainDomainMatcher(domain.Value))
} else {
matcher, err := NewRegexpDomainMatcher(domain.Value)
if err != nil {
return nil, err
}
anyCond.Add(matcher)
}
}
conds.Add(anyCond)
}
if len(this.Cidr) > 0 {
ipv4Net := v2net.NewIPNet()
ipv6Cond := NewAnyCondition()
hasIpv6 := false
for _, ip := range this.Cidr {
switch len(ip.Ip) {
case net.IPv4len:
ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
case net.IPv6len:
hasIpv6 = true
matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, false)
if err != nil {
return nil, err
}
ipv6Cond.Add(matcher)
default:
return nil, errors.New("Router: Invalid IP length.")
}
}
if !ipv4Net.IsEmpty() && hasIpv6 {
cond := NewAnyCondition()
cond.Add(NewIPv4Matcher(ipv4Net, false))
cond.Add(ipv6Cond)
conds.Add(cond)
} else if !ipv4Net.IsEmpty() {
conds.Add(NewIPv4Matcher(ipv4Net, false))
} else if hasIpv6 {
conds.Add(ipv6Cond)
}
}
if this.PortRange != nil {
conds.Add(NewPortMatcher(*this.PortRange))
}
if this.NetworkList != nil {
conds.Add(NewNetworkMatcher(this.NetworkList))
}
if len(this.SourceCidr) > 0 {
ipv4Net := v2net.NewIPNet()
ipv6Cond := NewAnyCondition()
hasIpv6 := false
for _, ip := range this.SourceCidr {
switch len(ip.Ip) {
case net.IPv4len:
ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
case net.IPv6len:
hasIpv6 = true
matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, true)
if err != nil {
return nil, err
}
ipv6Cond.Add(matcher)
default:
return nil, errors.New("Router: Invalid IP length.")
}
}
if !ipv4Net.IsEmpty() && hasIpv6 {
cond := NewAnyCondition()
cond.Add(NewIPv4Matcher(ipv4Net, true))
cond.Add(ipv6Cond)
conds.Add(cond)
} else if !ipv4Net.IsEmpty() {
conds.Add(NewIPv4Matcher(ipv4Net, true))
} else if hasIpv6 {
conds.Add(ipv6Cond)
}
}
if len(this.UserEmail) > 0 {
conds.Add(NewUserMatcher(this.UserEmail))
}
if len(this.InboundTag) > 0 {
conds.Add(NewInboundTagMatcher(this.InboundTag))
}
if conds.Len() == 0 {
return nil, errors.New("Router: This rule has no effective fields.")
}
return conds, nil
}

227
app/router/config.pb.go Normal file
View File

@@ -0,0 +1,227 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/app/router/config.proto
// DO NOT EDIT!
/*
Package router is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/app/router/config.proto
It has these top-level messages:
Domain
CIDR
RoutingRule
Config
*/
package router
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import v2ray_core_common_net "v2ray.com/core/common/net"
import v2ray_core_common_net1 "v2ray.com/core/common/net"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// Type of domain value.
type Domain_Type int32
const (
// The value is used as is.
Domain_Plain Domain_Type = 0
// The value is used as a regular expression.
Domain_Regex Domain_Type = 1
)
var Domain_Type_name = map[int32]string{
0: "Plain",
1: "Regex",
}
var Domain_Type_value = map[string]int32{
"Plain": 0,
"Regex": 1,
}
func (x Domain_Type) String() string {
return proto.EnumName(Domain_Type_name, int32(x))
}
func (Domain_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
type Config_DomainStrategy int32
const (
// Use domain as is.
Config_AsIs Config_DomainStrategy = 0
// Always resolve IP for domains.
Config_UseIp Config_DomainStrategy = 1
// Resolve to IP if the domain doesn't match any rules.
Config_IpIfNonMatch Config_DomainStrategy = 2
)
var Config_DomainStrategy_name = map[int32]string{
0: "AsIs",
1: "UseIp",
2: "IpIfNonMatch",
}
var Config_DomainStrategy_value = map[string]int32{
"AsIs": 0,
"UseIp": 1,
"IpIfNonMatch": 2,
}
func (x Config_DomainStrategy) String() string {
return proto.EnumName(Config_DomainStrategy_name, int32(x))
}
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} }
// Domain for routing decision.
type Domain struct {
// Domain matching type.
Type Domain_Type `protobuf:"varint,1,opt,name=type,enum=v2ray.core.app.router.Domain_Type" json:"type,omitempty"`
// Domain value.
Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
}
func (m *Domain) Reset() { *m = Domain{} }
func (m *Domain) String() string { return proto.CompactTextString(m) }
func (*Domain) ProtoMessage() {}
func (*Domain) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// IP for routing decision, in CIDR form.
type CIDR struct {
// IP address, should be either 4 or 16 bytes.
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
// Number of leading ones in the network mask.
Prefix uint32 `protobuf:"varint,2,opt,name=prefix" json:"prefix,omitempty"`
}
func (m *CIDR) Reset() { *m = CIDR{} }
func (m *CIDR) String() string { return proto.CompactTextString(m) }
func (*CIDR) ProtoMessage() {}
func (*CIDR) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type RoutingRule struct {
Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"`
Domain []*Domain `protobuf:"bytes,2,rep,name=domain" json:"domain,omitempty"`
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr" json:"cidr,omitempty"`
PortRange *v2ray_core_common_net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange" json:"port_range,omitempty"`
NetworkList *v2ray_core_common_net1.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList" json:"network_list,omitempty"`
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr" json:"source_cidr,omitempty"`
UserEmail []string `protobuf:"bytes,7,rep,name=user_email,json=userEmail" json:"user_email,omitempty"`
InboundTag []string `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag" json:"inbound_tag,omitempty"`
}
func (m *RoutingRule) Reset() { *m = RoutingRule{} }
func (m *RoutingRule) String() string { return proto.CompactTextString(m) }
func (*RoutingRule) ProtoMessage() {}
func (*RoutingRule) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *RoutingRule) GetDomain() []*Domain {
if m != nil {
return m.Domain
}
return nil
}
func (m *RoutingRule) GetCidr() []*CIDR {
if m != nil {
return m.Cidr
}
return nil
}
func (m *RoutingRule) GetPortRange() *v2ray_core_common_net.PortRange {
if m != nil {
return m.PortRange
}
return nil
}
func (m *RoutingRule) GetNetworkList() *v2ray_core_common_net1.NetworkList {
if m != nil {
return m.NetworkList
}
return nil
}
func (m *RoutingRule) GetSourceCidr() []*CIDR {
if m != nil {
return m.SourceCidr
}
return nil
}
type Config struct {
DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,enum=v2ray.core.app.router.Config_DomainStrategy" json:"domain_strategy,omitempty"`
Rule []*RoutingRule `protobuf:"bytes,2,rep,name=rule" json:"rule,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Config) GetRule() []*RoutingRule {
if m != nil {
return m.Rule
}
return nil
}
func init() {
proto.RegisterType((*Domain)(nil), "v2ray.core.app.router.Domain")
proto.RegisterType((*CIDR)(nil), "v2ray.core.app.router.CIDR")
proto.RegisterType((*RoutingRule)(nil), "v2ray.core.app.router.RoutingRule")
proto.RegisterType((*Config)(nil), "v2ray.core.app.router.Config")
proto.RegisterEnum("v2ray.core.app.router.Domain_Type", Domain_Type_name, Domain_Type_value)
proto.RegisterEnum("v2ray.core.app.router.Config_DomainStrategy", Config_DomainStrategy_name, Config_DomainStrategy_value)
}
func init() { proto.RegisterFile("v2ray.com/core/app/router/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 520 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x93, 0xd1, 0x6e, 0xd3, 0x3e,
0x14, 0xc6, 0xff, 0x69, 0xb3, 0xfc, 0x97, 0x93, 0x51, 0x22, 0x0b, 0x50, 0x18, 0x4c, 0x44, 0x11,
0x82, 0x5e, 0xa0, 0x04, 0x15, 0x01, 0x37, 0x48, 0x88, 0x75, 0xbb, 0xa8, 0x04, 0x53, 0x65, 0xb6,
0x1b, 0x6e, 0x22, 0x2f, 0x75, 0x83, 0x45, 0x62, 0x5b, 0x8e, 0x33, 0xd6, 0x87, 0xe0, 0xdd, 0x78,
0x24, 0x64, 0x3b, 0x13, 0x1b, 0x5a, 0xe1, 0xce, 0xe7, 0xf4, 0xf7, 0x1d, 0x7f, 0x3d, 0xfe, 0x02,
0xcf, 0x2e, 0x66, 0x8a, 0x6c, 0xf2, 0x4a, 0xb4, 0x45, 0x25, 0x14, 0x2d, 0x88, 0x94, 0x85, 0x12,
0xbd, 0xa6, 0xaa, 0xa8, 0x04, 0x5f, 0xb3, 0x3a, 0x97, 0x4a, 0x68, 0x81, 0xee, 0x5f, 0x71, 0x8a,
0xe6, 0x44, 0xca, 0xdc, 0x31, 0xfb, 0x4f, 0xff, 0x90, 0x57, 0xa2, 0x6d, 0x05, 0x2f, 0x38, 0xd5,
0x85, 0x14, 0x4a, 0x3b, 0xf1, 0xfe, 0xf3, 0xed, 0x14, 0xa7, 0xfa, 0xbb, 0x50, 0xdf, 0x1c, 0x98,
0x69, 0x08, 0x8e, 0x44, 0x4b, 0x18, 0x47, 0x6f, 0xc0, 0xd7, 0x1b, 0x49, 0x13, 0x2f, 0xf5, 0xa6,
0x93, 0x59, 0x96, 0xdf, 0x7a, 0x7d, 0xee, 0xe0, 0xfc, 0x74, 0x23, 0x29, 0xb6, 0x3c, 0xba, 0x07,
0x3b, 0x17, 0xa4, 0xe9, 0x69, 0x32, 0x4a, 0xbd, 0x69, 0x88, 0x5d, 0x91, 0x3d, 0x06, 0xdf, 0x30,
0x28, 0x84, 0x9d, 0x65, 0x43, 0x18, 0x8f, 0xff, 0x33, 0x47, 0x4c, 0x6b, 0x7a, 0x19, 0x7b, 0x59,
0x0e, 0xfe, 0x7c, 0x71, 0x84, 0xd1, 0x04, 0x46, 0x4c, 0xda, 0x1b, 0xf7, 0xf0, 0x88, 0x49, 0xf4,
0x00, 0x02, 0xa9, 0xe8, 0x9a, 0x5d, 0xda, 0x61, 0x77, 0xf0, 0x50, 0x65, 0x3f, 0xc6, 0x10, 0x61,
0xd1, 0x6b, 0xc6, 0x6b, 0xdc, 0x37, 0x14, 0xc5, 0x30, 0xd6, 0xa4, 0xb6, 0xc2, 0x10, 0x9b, 0x23,
0x7a, 0x0d, 0xc1, 0xca, 0x5a, 0x4b, 0x46, 0xe9, 0x78, 0x1a, 0xcd, 0x0e, 0xfe, 0xea, 0x1f, 0x0f,
0x30, 0x2a, 0xc0, 0xaf, 0xd8, 0x4a, 0x25, 0x63, 0x2b, 0x7a, 0xb4, 0x45, 0x64, 0xbc, 0x62, 0x0b,
0xa2, 0xf7, 0x00, 0x66, 0xcd, 0xa5, 0x22, 0xbc, 0xa6, 0x89, 0x9f, 0x7a, 0xd3, 0x68, 0x96, 0x5e,
0x97, 0xb9, 0x4d, 0xe7, 0x9c, 0xea, 0x7c, 0x29, 0x94, 0xc6, 0x86, 0xc3, 0xa1, 0xbc, 0x3a, 0xa2,
0x63, 0xd8, 0x1b, 0x5e, 0xa0, 0x6c, 0x58, 0xa7, 0x93, 0x1d, 0x3b, 0x22, 0xdb, 0x32, 0xe2, 0xc4,
0xa1, 0x1f, 0x59, 0xa7, 0x71, 0xc4, 0x7f, 0x17, 0xe8, 0x1d, 0x44, 0x9d, 0xe8, 0x55, 0x45, 0x4b,
0xeb, 0x3f, 0xf8, 0xb7, 0x7f, 0x70, 0xfc, 0xdc, 0xfc, 0x8b, 0x03, 0x80, 0xbe, 0xa3, 0xaa, 0xa4,
0x2d, 0x61, 0x4d, 0xf2, 0x7f, 0x3a, 0x9e, 0x86, 0x38, 0x34, 0x9d, 0x63, 0xd3, 0x40, 0x4f, 0x20,
0x62, 0xfc, 0x5c, 0xf4, 0x7c, 0x55, 0x9a, 0x35, 0xef, 0xda, 0xdf, 0x61, 0x68, 0x9d, 0x92, 0x3a,
0xfb, 0xe9, 0x41, 0x30, 0xb7, 0x61, 0x45, 0x67, 0x70, 0xd7, 0xed, 0xb2, 0xec, 0xb4, 0x22, 0x9a,
0xd6, 0x9b, 0x21, 0x41, 0x2f, 0xb6, 0x99, 0x71, 0x21, 0x77, 0x0f, 0xf1, 0x79, 0xd0, 0xe0, 0xc9,
0xea, 0x46, 0x6d, 0xd2, 0xa8, 0xfa, 0x86, 0x0e, 0xaf, 0xb9, 0x2d, 0x8d, 0xd7, 0x32, 0x81, 0x2d,
0x9f, 0xbd, 0x85, 0xc9, 0xcd, 0xc9, 0x68, 0x17, 0xfc, 0x0f, 0xdd, 0xa2, 0x73, 0x01, 0x3c, 0xeb,
0xe8, 0x42, 0xc6, 0x1e, 0x8a, 0x61, 0x6f, 0x21, 0x17, 0xeb, 0x13, 0xc1, 0x3f, 0x11, 0x5d, 0x7d,
0x8d, 0x47, 0x87, 0x2f, 0xe1, 0x61, 0x25, 0xda, 0xdb, 0xef, 0x39, 0x8c, 0x9c, 0xe9, 0xa5, 0xf9,
0x64, 0xbe, 0x04, 0xae, 0x79, 0x1e, 0xd8, 0x2f, 0xe8, 0xd5, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff,
0xe4, 0x89, 0x6f, 0xa7, 0xd1, 0x03, 0x00, 0x00,
}

61
app/router/config.proto Normal file
View File

@@ -0,0 +1,61 @@
syntax = "proto3";
package v2ray.core.app.router;
option go_package = "router";
option java_package = "com.v2ray.core.app.router";
option java_outer_classname = "ConfigProto";
import "v2ray.com/core/common/net/port.proto";
import "v2ray.com/core/common/net/network.proto";
// Domain for routing decision.
message Domain {
// Type of domain value.
enum Type {
// The value is used as is.
Plain = 0;
// The value is used as a regular expression.
Regex = 1;
}
// Domain matching type.
Type type = 1;
// Domain value.
string value = 2;
}
// IP for routing decision, in CIDR form.
message CIDR {
// IP address, should be either 4 or 16 bytes.
bytes ip = 1;
// Number of leading ones in the network mask.
uint32 prefix = 2;
}
message RoutingRule {
string tag = 1;
repeated Domain domain = 2;
repeated CIDR cidr = 3;
v2ray.core.common.net.PortRange port_range = 4;
v2ray.core.common.net.NetworkList network_list = 5;
repeated CIDR source_cidr = 6;
repeated string user_email = 7;
repeated string inbound_tag = 8;
}
message Config {
enum DomainStrategy {
// Use domain as is.
AsIs = 0;
// Always resolve IP for domains.
UseIp = 1;
// Resolve to IP if the domain doesn't match any rules.
IpIfNonMatch = 2;
}
DomainStrategy domain_strategy = 1;
repeated RoutingRule rule = 2;
}

View File

@@ -1,29 +0,0 @@
package router
import (
"v2ray.com/core/common"
)
type ConfigObjectCreator func([]byte) (interface{}, error)
var (
configCache map[string]ConfigObjectCreator
)
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, common.ErrObjectNotFound
}
return creator(data)
}
func init() {
configCache = make(map[string]ConfigObjectCreator)
}

View File

@@ -1,28 +0,0 @@
// +build json
package router
import (
"encoding/json"
"v2ray.com/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
}

View File

@@ -1,41 +1,130 @@
package router
import (
"errors"
"v2ray.com/core/app"
"v2ray.com/core/common"
"v2ray.com/core/app/dns"
"v2ray.com/core/common/loader"
"v2ray.com/core/common/log"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
)
const (
APP_ID = app.ID(3)
)
type Router interface {
common.Releasable
TakeDetour(v2net.Destination) (string, error)
}
type RouterFactory interface {
Create(rawConfig interface{}, space app.Space) (Router, error)
}
var (
routerCache = make(map[string]RouterFactory)
ErrInvalidRule = errors.New("Invalid Rule")
ErrNoRuleApplicable = errors.New("No rule applicable")
)
func RegisterRouter(name string, factory RouterFactory) error {
if _, found := routerCache[name]; found {
return common.ErrDuplicatedName
}
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)),
}
log.Error("Router: not found: ", name)
return nil, common.ErrObjectNotFound
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) {
return errors.New("Router: DNS is not found in the space.")
}
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
return nil
})
return r
}
func (this *Router) Release() {
}
// Private: Visible for testing.
func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
ips := this.dnsServer.Get(dest.Address.Domain())
if len(ips) == 0 {
return nil
}
dests := make([]v2net.Destination, len(ips))
for idx, ip := range ips {
if dest.Network == v2net.Network_TCP {
dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port)
} else {
dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port)
}
}
return dests
}
func (this *Router) takeDetourWithoutCache(session *proxy.SessionInfo) (string, error) {
for _, rule := range this.rules {
if rule.Apply(session) {
return rule.Tag, nil
}
}
dest := session.Destination
if this.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() {
log.Info("Router: Looking up IP for ", dest)
ipDests := this.ResolveIP(dest)
if ipDests != nil {
for _, ipDest := range ipDests {
log.Info("Router: Trying IP ", ipDest)
for _, rule := range this.rules {
if rule.Apply(&proxy.SessionInfo{
Source: session.Source,
Destination: ipDest,
User: session.User,
}) {
return rule.Tag, nil
}
}
}
}
}
return "", ErrNoRuleApplicable
}
func (this *Router) TakeDetour(session *proxy.SessionInfo) (string, error) {
//destStr := dest.String()
//found, tag, err := this.cache.Get(destStr)
//if !found {
tag, err := this.takeDetourWithoutCache(session)
//this.cache.Set(destStr, tag, err)
return tag, err
//}
//return tag, err
}
type RouterFactory struct{}
func (RouterFactory) Create(space app.Space, config interface{}) (app.Application, error) {
router := NewRouter(config.(*Config), space)
return router, nil
}
func (RouterFactory) AppId() app.ID {
return APP_ID
}
func init() {
app.RegisterApplicationFactory(loader.GetType(new(Config)), RouterFactory{})
}

View File

@@ -1,4 +1,4 @@
package rules_test
package router_test
import (
"testing"
@@ -8,20 +8,22 @@ import (
dispatchers "v2ray.com/core/app/dispatcher/impl"
"v2ray.com/core/app/dns"
"v2ray.com/core/app/proxyman"
"v2ray.com/core/app/router"
. "v2ray.com/core/app/router/rules"
. "v2ray.com/core/app/router"
v2net "v2ray.com/core/common/net"
"v2ray.com/core/proxy"
"v2ray.com/core/testing/assert"
)
func TestSimpleRouter(t *testing.T) {
assert := assert.On(t)
config := &RouterRuleConfig{
Rules: []*Rule{
config := &Config{
Rule: []*RoutingRule{
{
Tag: "test",
Condition: NewNetworkMatcher(v2net.Network_TCP.AsList()),
Tag: "test",
NetworkList: &v2net.NetworkList{
Network: []v2net.Network{v2net.Network_TCP},
},
},
},
}
@@ -31,10 +33,10 @@ func TestSimpleRouter(t *testing.T) {
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)
space.BindApp(APP_ID, r)
assert.Error(space.Initialize()).IsNil()
tag, err := r.TakeDetour(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80))
tag, err := r.TakeDetour(&proxy.SessionInfo{Destination: v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80)})
assert.Error(err).IsNil()
assert.String(tag).Equals("test")
}

View File

@@ -1,4 +1,4 @@
package rules
package router
import (
"sync"

View File

@@ -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),
}
}

View File

@@ -1,83 +0,0 @@
// +build generate
package main
import (
"bufio"
"fmt"
"log"
"math"
"net"
"net/http"
"os"
"strconv"
"strings"
v2net "v2ray.com/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 \"v2ray.com/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

View File

@@ -1,19 +0,0 @@
// +build json
package rules
import (
"encoding/json"
"v2ray.com/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
}

View File

@@ -1,26 +0,0 @@
// +build json
package rules_test
import (
"testing"
. "v2ray.com/core/app/router/rules"
"v2ray.com/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()
}

View File

@@ -1,27 +0,0 @@
package rules_test
import (
"net"
"testing"
. "v2ray.com/core/app/router/rules"
v2net "v2ray.com/core/common/net"
"v2ray.com/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()
}

View File

@@ -1,21 +0,0 @@
// +build json
package rules
import (
"encoding/json"
"v2ray.com/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
}

View File

@@ -1,26 +0,0 @@
// +build json
package rules_test
import (
"testing"
. "v2ray.com/core/app/router/rules"
"v2ray.com/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()
}

View File

@@ -1,25 +0,0 @@
package rules_test
import (
"testing"
. "v2ray.com/core/app/router/rules"
v2net "v2ray.com/core/common/net"
"v2ray.com/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()
}

View File

@@ -1,27 +0,0 @@
package rules
import (
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)
}
type DomainStrategy int
var (
DomainAsIs = DomainStrategy(0)
AlwaysUseIP = DomainStrategy(1)
UseIPIfNonMatch = DomainStrategy(2)
)
type RouterRuleConfig struct {
Rules []*Rule
DomainStrategy DomainStrategy
}

View File

@@ -1,143 +0,0 @@
// +build json
package rules
import (
"encoding/json"
"errors"
"strings"
router "v2ray.com/core/app/router"
"v2ray.com/core/common/collect"
"v2ray.com/core/common/log"
v2net "v2ray.com/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
})
}

View File

@@ -1,51 +0,0 @@
// +build json
package rules_test
import (
"testing"
. "v2ray.com/core/app/router/rules"
v2net "v2ray.com/core/common/net"
"v2ray.com/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()
}

View File

@@ -1,105 +0,0 @@
package rules
import (
"errors"
"v2ray.com/core/app"
"v2ray.com/core/app/dns"
"v2ray.com/core/app/router"
"v2ray.com/core/common/log"
v2net "v2ray.com/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: 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.config.Rules {
if rule.Apply(dest) {
return rule.Tag, nil
}
}
if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address.Family().IsDomain() {
log.Info("Router: Looking up IP for ", dest)
ipDests := this.ResolveIP(dest)
if ipDests != nil {
for _, ipDest := range ipDests {
log.Info("Router: Trying IP ", ipDest)
for _, rule := range this.config.Rules {
if rule.Apply(ipDest) {
return rule.Tag, nil
}
}
}
}
}
return "", ErrNoRuleApplicable
}
func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
destStr := dest.String()
found, tag, err := this.cache.Get(destStr)
if !found {
tag, err := this.takeDetourWithoutCache(dest)
this.cache.Set(destStr, tag, err)
return tag, err
}
return tag, err
}
type RouterFactory struct {
}
func (this *RouterFactory) Create(rawConfig interface{}, space app.Space) (router.Router, error) {
return NewRouter(rawConfig.(*RouterRuleConfig), space), nil
}
func init() {
router.RegisterRouter("rules", &RouterFactory{})
}

View File

@@ -6,10 +6,6 @@ import (
"v2ray.com/core/common"
)
var (
ErrMissingApplication = errors.New("App: Failed to found one or more applications.")
)
type ID int
// Context of a function call from proxy to app.
@@ -26,6 +22,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 +45,7 @@ type Space interface {
HasApp(ID) bool
GetApp(ID) Application
BindApp(ID, Application)
BindFromConfig(name string, config interface{}) error
}
type spaceImpl struct {
@@ -80,3 +90,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
}

View File

@@ -55,7 +55,7 @@ func (b *Buffer) Clear() *Buffer {
// Reset resets this Buffer into its original state.
func (b *Buffer) Reset() *Buffer {
b.offset = defaultOffset
b.Value = b.head
b.Value = b.head[b.offset:]
return b
}
@@ -190,9 +190,7 @@ func (b *Buffer) FillFrom(reader io.Reader) (int, error) {
begin := b.Len()
b.Value = b.Value[:cap(b.Value)]
nBytes, err := reader.Read(b.Value[begin:])
if err == nil {
b.Value = b.Value[:begin+nBytes]
}
b.Value = b.Value[:begin+nBytes]
return nBytes, err
}
@@ -200,31 +198,13 @@ func (b *Buffer) String() string {
return string(b.Value)
}
// NewSmallBuffer creates a Buffer with 1K bytes of arbitrary content.
func NewSmallBuffer() *Buffer {
return smallPool.Allocate()
}
// NewBuffer creates a Buffer with 8K bytes of arbitrary content.
func NewBuffer() *Buffer {
return mediumPool.Allocate()
}
// NewLargeBuffer creates a Buffer with 64K bytes of arbitrary content.
func NewLargeBuffer() *Buffer {
return largePool.Allocate()
}
func NewBufferWithSize(size int) *Buffer {
if size <= SmallBufferSize {
return NewSmallBuffer()
}
if size <= BufferSize {
return NewBuffer()
}
return NewLargeBuffer()
func NewSmallBuffer() *Buffer {
return smallPool.Allocate()
}
func NewLocalBuffer(size int) *Buffer {

View File

@@ -11,6 +11,31 @@ type Pool interface {
Free(*Buffer)
}
type SyncPool struct {
allocator *sync.Pool
}
func NewSyncPool(bufferSize uint32) *SyncPool {
pool := &SyncPool{
allocator: &sync.Pool{
New: func() interface{} { return make([]byte, bufferSize) },
},
}
return pool
}
func (p *SyncPool) Allocate() *Buffer {
return CreateBuffer(p.allocator.Get().([]byte), p)
}
func (p *SyncPool) Free(buffer *Buffer) {
rawBuffer := buffer.head
if rawBuffer == nil {
return
}
p.allocator.Put(rawBuffer)
}
type BufferPool struct {
chain chan []byte
allocator *sync.Pool
@@ -52,21 +77,18 @@ func (p *BufferPool) Free(buffer *Buffer) {
}
const (
SmallBufferSize = 1600 - defaultOffset
mediumBufferByteSize = 8 * 1024
BufferSize = mediumBufferByteSize - defaultOffset
largeBufferByteSize = 64 * 1024
LargeBufferSize = largeBufferByteSize - defaultOffset
smallBufferByteSize = 2 * 1024
SmallBufferSize = smallBufferByteSize - defaultOffset
PoolSizeEnvKey = "v2ray.buffer.size"
)
var (
smallPool = NewBufferPool(1600, 256)
mediumPool *BufferPool
largePool *BufferPool
smallPool = NewSyncPool(2048)
)
func init() {
@@ -79,6 +101,5 @@ func init() {
}
}
totalByteSize := size * 1024 * 1024
mediumPool = NewBufferPool(mediumBufferByteSize, totalByteSize/4*3/mediumBufferByteSize)
largePool = NewBufferPool(largeBufferByteSize, totalByteSize/4/largeBufferByteSize)
mediumPool = NewBufferPool(mediumBufferByteSize, totalByteSize/mediumBufferByteSize)
}

View File

@@ -58,3 +58,31 @@ func TestBufferString(t *testing.T) {
buffer.AppendString("Test String")
assert.String(buffer.String()).Equals("Test String")
}
func BenchmarkNewBuffer8192(b *testing.B) {
for i := 0; i < b.N; i++ {
buffer := NewBuffer()
buffer.Release()
}
}
func BenchmarkNewLocalBuffer8192(b *testing.B) {
for i := 0; i < b.N; i++ {
buffer := NewLocalBuffer(8192)
buffer.Release()
}
}
func BenchmarkNewBuffer2048(b *testing.B) {
for i := 0; i < b.N; i++ {
buffer := NewSmallBuffer()
buffer.Release()
}
}
func BenchmarkNewLocalBuffer2048(b *testing.B) {
for i := 0; i < b.N; i++ {
buffer := NewLocalBuffer(2048)
buffer.Release()
}
}

View File

@@ -1,12 +0,0 @@
package collect
type StringList []string
func NewStringList(raw []string) *StringList {
list := StringList(raw)
return &list
}
func (this StringList) Len() int {
return len(this)
}

View File

@@ -1,25 +0,0 @@
// +build json
package collect
import (
"encoding/json"
"errors"
"strings"
)
func (this *StringList) UnmarshalJSON(data []byte) error {
var strarray []string
if err := json.Unmarshal(data, &strarray); err == nil {
*this = *NewStringList(strarray)
return nil
}
var rawstr string
if err := json.Unmarshal(data, &rawstr); err == nil {
strlist := strings.Split(rawstr, ",")
*this = *NewStringList(strlist)
return nil
}
return errors.New("Unknown format of a string list: " + string(data))
}

View File

@@ -1,30 +0,0 @@
// +build json
package collect_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/common/collect"
"v2ray.com/core/testing/assert"
)
func TestStringListUnmarshalError(t *testing.T) {
assert := assert.On(t)
rawJson := `1234`
list := new(StringList)
err := json.Unmarshal([]byte(rawJson), list)
assert.Error(err).IsNotNil()
}
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)
}

View File

@@ -11,7 +11,7 @@ import (
func TestBufferedReader(t *testing.T) {
assert := assert.On(t)
content := alloc.NewLargeBuffer()
content := alloc.NewBuffer()
len := content.Len()
reader := NewBufferedReader(content)
@@ -31,13 +31,4 @@ func TestBufferedReader(t *testing.T) {
assert.Error(err).IsNil()
assert.Int(content.Len()).Equals(len2)
reader.SetCached(false)
payload2 := alloc.NewBuffer()
reader.Read(payload2.Value)
assert.Int(content.Len()).Equals(len2)
reader.Read(payload2.Value)
assert.Int(content.Len()).LessThan(len2)
}

View File

@@ -3,7 +3,6 @@ package io
import (
"io"
"sync"
"v2ray.com/core/common/alloc"
)
@@ -27,7 +26,7 @@ func (this *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
defer this.Unlock()
if this.writer == nil {
return 0, io.EOF
return 0, io.ErrClosedPipe
}
totalBytes := int64(0)
@@ -49,7 +48,7 @@ func (this *BufferedWriter) Write(b []byte) (int, error) {
defer this.Unlock()
if this.writer == nil {
return 0, io.EOF
return 0, io.ErrClosedPipe
}
if !this.cached {
@@ -67,7 +66,7 @@ func (this *BufferedWriter) Flush() error {
defer this.Unlock()
if this.writer == nil {
return io.EOF
return io.ErrClosedPipe
}
return this.FlushWithoutLock()

View File

@@ -11,7 +11,7 @@ import (
func TestBufferedWriter(t *testing.T) {
assert := assert.On(t)
content := alloc.NewLargeBuffer().Clear()
content := alloc.NewBuffer().Clear()
writer := NewBufferedWriter(content)
assert.Bool(writer.Cached()).IsTrue()

View File

@@ -19,25 +19,33 @@ func NewChainWriter(writer Writer) *ChainWriter {
}
func (this *ChainWriter) Write(payload []byte) (int, error) {
if this.writer == nil {
return 0, io.EOF
}
size := len(payload)
buffer := alloc.NewBufferWithSize(size).Clear()
buffer.Append(payload)
this.Lock()
defer this.Unlock()
if this.writer == nil {
return 0, io.EOF
return 0, io.ErrClosedPipe
}
err := this.writer.Write(buffer)
if err != nil {
return 0, err
bytesWritten := 0
size := len(payload)
for size > 0 {
buffer := alloc.NewBuffer().Clear()
if size > alloc.BufferSize {
buffer.Append(payload[:alloc.BufferSize])
size -= alloc.BufferSize
payload = payload[alloc.BufferSize:]
bytesWritten += alloc.BufferSize
} else {
buffer.Append(payload)
bytesWritten += size
size = 0
}
err := this.writer.Write(buffer)
if err != nil {
return bytesWritten, err
}
}
return size, nil
return bytesWritten, nil
}
func (this *ChainWriter) Release() {

View File

@@ -15,11 +15,9 @@ type ChanReader struct {
}
func NewChanReader(stream Reader) *ChanReader {
this := &ChanReader{
return &ChanReader{
stream: stream,
}
this.Fill()
return this
}
// Private: Visible for testing.

View File

@@ -38,12 +38,6 @@ func (this *AdaptiveReader) Read() (*alloc.Buffer, error) {
return nil, err
}
if buffer.Len() >= alloc.BufferSize {
this.allocate = alloc.NewLargeBuffer
} else {
this.allocate = alloc.NewBuffer
}
return buffer, nil
}

View File

@@ -19,9 +19,4 @@ func TestAdaptiveReader(t *testing.T) {
assert.Error(err).IsNil()
assert.Bool(b1.IsFull()).IsTrue()
assert.Int(b1.Len()).Equals(alloc.BufferSize)
b2, err := reader.Read()
assert.Error(err).IsNil()
assert.Bool(b2.IsFull()).IsTrue()
assert.Int(b2.Len()).Equals(alloc.LargeBufferSize)
}

View File

@@ -1,6 +1,7 @@
package io
import (
"io"
"v2ray.com/core/common/log"
)
@@ -25,3 +26,11 @@ func Pipe(reader Reader, writer Writer) error {
}
}
}
func PipeUntilEOF(reader Reader, writer Writer) error {
err := Pipe(reader, writer)
if err != nil && err != io.EOF {
return err
}
return nil
}

View File

@@ -13,7 +13,7 @@ import (
func TestAdaptiveWriter(t *testing.T) {
assert := assert.On(t)
lb := alloc.NewLargeBuffer()
lb := alloc.NewBuffer()
rand.Read(lb.Value)
writeBuffer := make([]byte, 0, 1024*1024)

View File

@@ -1,39 +0,0 @@
// +build json
package loader_test
import (
"testing"
. "v2ray.com/core/common/loader"
"v2ray.com/core/testing/assert"
)
type TestConfigA struct {
V int
}
type TestConfigB struct {
S string
}
func TestCreatorCache(t *testing.T) {
assert := assert.On(t)
cache := ConfigCreatorCache{}
creator1 := func() interface{} { return &TestConfigA{} }
creator2 := func() interface{} { return &TestConfigB{} }
cache.RegisterCreator("1", creator1)
loader := NewJSONConfigLoader(cache, "test", "")
rawA, err := loader.LoadWithID([]byte(`{"V": 2}`), "1")
assert.Error(err).IsNil()
instA := rawA.(*TestConfigA)
assert.Int(instA.V).Equals(2)
cache.RegisterCreator("2", creator2)
rawB, err := loader.LoadWithID([]byte(`{"S": "a"}`), "2")
assert.Error(err).IsNil()
instB := rawB.(*TestConfigB)
assert.String(instB.S).Equals("a")
}

View File

@@ -1,36 +0,0 @@
package loader
import (
"errors"
"v2ray.com/core/common"
)
var (
ErrUnknownConfigID = errors.New("Unknown config ID.")
)
type ConfigCreator func() interface{}
type ConfigCreatorCache map[string]ConfigCreator
func (this ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error {
if _, found := this[id]; found {
return common.ErrDuplicatedName
}
this[id] = creator
return nil
}
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
View File

@@ -0,0 +1,50 @@
package loader
import (
"errors"
"reflect"
"github.com/golang/protobuf/proto"
)
func NewTypedSettings(message proto.Message) *TypedSettings {
if message == nil {
return nil
}
settings, _ := proto.Marshal(message)
return &TypedSettings{
Type: GetType(message),
Settings: settings,
}
}
func GetType(message proto.Message) string {
return proto.MessageName(message)
}
func GetInstance(messageType string) (interface{}, error) {
mType := proto.MessageType(messageType).Elem()
if mType == nil {
return nil, errors.New("Unknown type: " + messageType)
}
return reflect.New(mType).Interface(), nil
}
func (this *TypedSettings) Load(message proto.Message) error {
targetType := GetType(message)
if targetType != this.Type {
return errors.New("Have type " + this.Type + ", but retrieved for " + targetType)
}
return proto.Unmarshal(this.Settings, message)
}
func (this *TypedSettings) GetInstance() (interface{}, error) {
instance, err := GetInstance(this.Type)
if err != nil {
return nil, err
}
if err := proto.Unmarshal(this.Settings, instance.(proto.Message)); err != nil {
return nil, err
}
return instance, nil
}

62
common/loader/type.pb.go Normal file
View File

@@ -0,0 +1,62 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/common/loader/type.proto
// DO NOT EDIT!
/*
Package loader is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/common/loader/type.proto
It has these top-level messages:
TypedSettings
*/
package loader
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// Serialized proto message along with its type name.
type TypedSettings struct {
// The name of the message type, retrieved from protobuf API.
Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
// Serialized proto message.
Settings []byte `protobuf:"bytes,2,opt,name=settings,proto3" json:"settings,omitempty"`
}
func (m *TypedSettings) Reset() { *m = TypedSettings{} }
func (m *TypedSettings) String() string { return proto.CompactTextString(m) }
func (*TypedSettings) ProtoMessage() {}
func (*TypedSettings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func init() {
proto.RegisterType((*TypedSettings)(nil), "v2ray.core.common.loader.TypedSettings")
}
func init() { proto.RegisterFile("v2ray.com/core/common/loader/type.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 151 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x52, 0x2f, 0x33, 0x2a, 0x4a,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcd, 0xcd,
0xcf, 0xd3, 0xcf, 0xc9, 0x4f, 0x4c, 0x49, 0x2d, 0xd2, 0x2f, 0xa9, 0x2c, 0x48, 0xd5, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0x92, 0x80, 0x29, 0x2c, 0x4a, 0xd5, 0x83, 0x28, 0xd2, 0x83, 0x28, 0x52,
0xb2, 0xe7, 0xe2, 0x0d, 0xa9, 0x2c, 0x48, 0x4d, 0x09, 0x4e, 0x2d, 0x29, 0xc9, 0xcc, 0x4b, 0x2f,
0x16, 0x12, 0xe2, 0x62, 0x01, 0x69, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x85,
0xa4, 0xb8, 0x38, 0x8a, 0xa1, 0xf2, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x70, 0xbe, 0x93,
0x21, 0x97, 0x4c, 0x72, 0x7e, 0xae, 0x1e, 0x2e, 0x0b, 0x9c, 0x38, 0x41, 0xc6, 0x07, 0x80, 0x5c,
0x11, 0xc5, 0x06, 0x11, 0x4a, 0x62, 0x03, 0x3b, 0xca, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x24,
0xa2, 0x4d, 0x76, 0xbf, 0x00, 0x00, 0x00,
}

14
common/loader/type.proto Normal file
View File

@@ -0,0 +1,14 @@
syntax = "proto3";
package v2ray.core.common.loader;
option go_package = "loader";
option java_package = "com.v2ray.core.common.loader";
option java_outer_classname = "TypeProto";
// Serialized proto message along with its type name.
message TypedSettings {
// The name of the message type, retrieved from protobuf API.
string type = 1;
// Serialized proto message.
bytes settings = 2;
}

25
common/log/config.go Normal file
View 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
View 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
View 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;
}

View File

@@ -62,6 +62,9 @@ func (this *FileLogWriter) Log(log LogEntry) {
}
func (this *FileLogWriter) run() {
this.cancel.WaitThread()
defer this.cancel.FinishThread()
for {
entry, open := <-this.queue
if !open {
@@ -69,12 +72,11 @@ func (this *FileLogWriter) run() {
}
this.logger.Print(entry + platform.LineSeparator())
}
this.cancel.Done()
}
func (this *FileLogWriter) Close() {
close(this.queue)
<-this.cancel.WaitForDone()
this.cancel.WaitForDone()
this.file.Close()
}

View File

@@ -1,19 +1,10 @@
package log
import (
"errors"
"v2ray.com/core/common/log/internal"
)
type LogLevel int
const (
DebugLevel = LogLevel(0)
InfoLevel = LogLevel(1)
WarningLevel = LogLevel(2)
ErrorLevel = LogLevel(3)
NoneLevel = LogLevel(999)
)
var (
streamLoggerInstance internal.LogWriter = internal.NewStdOutLogWriter()
@@ -25,35 +16,30 @@ 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 {
logger, err := internal.NewFileLogWriter(file)
if err != nil {
Error("Failed to create error logger on file (", file, "): ", err)
return err
return errors.New("Log:Failed to create error logger on file (" + file + "): " + err.Error())
}
streamLoggerInstance = logger
return nil

View File

@@ -187,15 +187,15 @@ func (this *domainAddress) Equals(another Address) bool {
return this.Domain() == anotherDomain.Domain()
}
func (this *AddressPB) AsAddress() Address {
func (this *IPOrDomain) AsAddress() Address {
if this == nil {
return nil
}
switch addr := this.Address.(type) {
case *AddressPB_Ip:
case *IPOrDomain_Ip:
return IPAddress(addr.Ip)
case *AddressPB_Domain:
case *IPOrDomain_Domain:
return DomainAddress(addr.Domain)
}
panic("Common|Net: Invalid AddressPB.")
panic("Common|Net: Invalid address.")
}

View File

@@ -12,8 +12,8 @@ It is generated from these files:
v2ray.com/core/common/net/port.proto
It has these top-level messages:
AddressPB
DestinationPB
IPOrDomain
Endpoint
NetworkList
PortRange
*/
@@ -34,109 +34,109 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type AddressPB struct {
type IPOrDomain struct {
// Types that are valid to be assigned to Address:
// *AddressPB_Ip
// *AddressPB_Domain
Address isAddressPB_Address `protobuf_oneof:"address"`
// *IPOrDomain_Ip
// *IPOrDomain_Domain
Address isIPOrDomain_Address `protobuf_oneof:"address"`
}
func (m *AddressPB) Reset() { *m = AddressPB{} }
func (m *AddressPB) String() string { return proto.CompactTextString(m) }
func (*AddressPB) ProtoMessage() {}
func (*AddressPB) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
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 isAddressPB_Address interface {
isAddressPB_Address()
type isIPOrDomain_Address interface {
isIPOrDomain_Address()
}
type AddressPB_Ip struct {
type IPOrDomain_Ip struct {
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3,oneof"`
}
type AddressPB_Domain struct {
type IPOrDomain_Domain struct {
Domain string `protobuf:"bytes,2,opt,name=domain,oneof"`
}
func (*AddressPB_Ip) isAddressPB_Address() {}
func (*AddressPB_Domain) isAddressPB_Address() {}
func (*IPOrDomain_Ip) isIPOrDomain_Address() {}
func (*IPOrDomain_Domain) isIPOrDomain_Address() {}
func (m *AddressPB) GetAddress() isAddressPB_Address {
func (m *IPOrDomain) GetAddress() isIPOrDomain_Address {
if m != nil {
return m.Address
}
return nil
}
func (m *AddressPB) GetIp() []byte {
if x, ok := m.GetAddress().(*AddressPB_Ip); ok {
func (m *IPOrDomain) GetIp() []byte {
if x, ok := m.GetAddress().(*IPOrDomain_Ip); ok {
return x.Ip
}
return nil
}
func (m *AddressPB) GetDomain() string {
if x, ok := m.GetAddress().(*AddressPB_Domain); ok {
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 (*AddressPB) 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 _AddressPB_OneofMarshaler, _AddressPB_OneofUnmarshaler, _AddressPB_OneofSizer, []interface{}{
(*AddressPB_Ip)(nil),
(*AddressPB_Domain)(nil),
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 _AddressPB_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*AddressPB)
func _IPOrDomain_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*IPOrDomain)
// address
switch x := m.Address.(type) {
case *AddressPB_Ip:
case *IPOrDomain_Ip:
b.EncodeVarint(1<<3 | proto.WireBytes)
b.EncodeRawBytes(x.Ip)
case *AddressPB_Domain:
case *IPOrDomain_Domain:
b.EncodeVarint(2<<3 | proto.WireBytes)
b.EncodeStringBytes(x.Domain)
case nil:
default:
return fmt.Errorf("AddressPB.Address has unexpected type %T", x)
return fmt.Errorf("IPOrDomain.Address has unexpected type %T", x)
}
return nil
}
func _AddressPB_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*AddressPB)
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 = &AddressPB_Ip{x}
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 = &AddressPB_Domain{x}
m.Address = &IPOrDomain_Domain{x}
return true, err
default:
return false, nil
}
}
func _AddressPB_OneofSizer(msg proto.Message) (n int) {
m := msg.(*AddressPB)
func _IPOrDomain_OneofSizer(msg proto.Message) (n int) {
m := msg.(*IPOrDomain)
// address
switch x := m.Address.(type) {
case *AddressPB_Ip:
case *IPOrDomain_Ip:
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(len(x.Ip)))
n += len(x.Ip)
case *AddressPB_Domain:
case *IPOrDomain_Domain:
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(len(x.Domain)))
n += len(x.Domain)
@@ -148,21 +148,22 @@ func _AddressPB_OneofSizer(msg proto.Message) (n int) {
}
func init() {
proto.RegisterType((*AddressPB)(nil), "v2ray.core.common.net.AddressPB")
proto.RegisterType((*IPOrDomain)(nil), "v2ray.core.common.net.IPOrDomain")
}
func init() { proto.RegisterFile("v2ray.com/core/common/net/address.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 159 bytes of a gzipped FileDescriptorProto
// 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, 0xe2, 0xe2, 0x74, 0x84, 0xa8, 0x0b, 0x70, 0x12, 0x12, 0xe0, 0x62, 0xca, 0x2c, 0x90,
0x60, 0x54, 0x60, 0xd4, 0xe0, 0xf1, 0x60, 0x08, 0x62, 0xca, 0x2c, 0x10, 0x92, 0xe0, 0x62, 0x4b,
0xc9, 0xcf, 0x4d, 0xcc, 0xcc, 0x93, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0xf4, 0x60, 0x08, 0x82, 0xf2,
0x9d, 0x38, 0xb9, 0xd8, 0xa1, 0x16, 0x38, 0xe9, 0x71, 0x49, 0x26, 0xe7, 0xe7, 0xea, 0x61, 0xb5,
0xc0, 0x89, 0x07, 0x66, 0x3c, 0xc8, 0x15, 0x51, 0xcc, 0x79, 0xa9, 0x25, 0x49, 0x6c, 0x60, 0x17,
0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa1, 0xd1, 0xe6, 0x14, 0xbc, 0x00, 0x00, 0x00,
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,
}

View File

@@ -5,9 +5,12 @@ option go_package = "net";
option java_package = "com.v2ray.core.common.net";
option java_outer_classname = "AddressProto";
message AddressPB {
message IPOrDomain {
oneof address {
// IP address. Must by either 4 or 16 bytes.
bytes ip = 1;
// Domain address.
string domain = 2;
}
}

View File

@@ -1,27 +0,0 @@
// +build json
package net
import (
"encoding/json"
)
func (this *AddressPB) UnmarshalJSON(data []byte) error {
var rawStr string
if err := json.Unmarshal(data, &rawStr); err != nil {
return err
}
addr := ParseAddress(rawStr)
switch addr.Family() {
case AddressFamilyIPv4, AddressFamilyIPv6:
this.Address = &AddressPB_Ip{
Ip: []byte(addr.IP()),
}
case AddressFamilyDomain:
this.Address = &AddressPB_Domain{
Domain: addr.Domain(),
}
}
return nil
}

View File

@@ -1,40 +0,0 @@
// +build json
package net_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/common/net"
"v2ray.com/core/testing/assert"
)
func TestIPParsing(t *testing.T) {
assert := assert.On(t)
rawJson := "\"8.8.8.8\""
var address AddressPB
err := json.Unmarshal([]byte(rawJson), &address)
assert.Error(err).IsNil()
assert.Bytes(address.GetIp()).Equals([]byte{8, 8, 8, 8})
}
func TestDomainParsing(t *testing.T) {
assert := assert.On(t)
rawJson := "\"v2ray.com\""
var address AddressPB
err := json.Unmarshal([]byte(rawJson), &address)
assert.Error(err).IsNil()
assert.String(address.GetDomain()).Equals("v2ray.com")
}
func TestInvalidAddressJson(t *testing.T) {
assert := assert.On(t)
rawJson := "1234"
var address AddressPB
err := json.Unmarshal([]byte(rawJson), &address)
assert.Error(err).IsNotNil()
}

View File

@@ -52,7 +52,7 @@ func (this Destination) Equals(another Destination) bool {
return this.Network == another.Network && this.Port == another.Port && this.Address.Equals(another.Address)
}
func (this *DestinationPB) AsDestination() Destination {
func (this *Endpoint) AsDestination() Destination {
return Destination{
Network: this.Network,
Address: this.Address.AsAddress(),

View File

@@ -13,18 +13,18 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
type DestinationPB struct {
Network Network `protobuf:"varint,1,opt,name=network,enum=v2ray.core.common.net.Network" json:"network,omitempty"`
Address *AddressPB `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
Port uint32 `protobuf:"varint,3,opt,name=port" json:"port,omitempty"`
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 *DestinationPB) Reset() { *m = DestinationPB{} }
func (m *DestinationPB) String() string { return proto.CompactTextString(m) }
func (*DestinationPB) ProtoMessage() {}
func (*DestinationPB) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
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 *DestinationPB) GetAddress() *AddressPB {
func (m *Endpoint) GetAddress() *IPOrDomain {
if m != nil {
return m.Address
}
@@ -32,25 +32,25 @@ func (m *DestinationPB) GetAddress() *AddressPB {
}
func init() {
proto.RegisterType((*DestinationPB)(nil), "v2ray.core.common.net.DestinationPB")
proto.RegisterType((*Endpoint)(nil), "v2ray.core.common.net.Endpoint")
}
func init() { proto.RegisterFile("v2ray.com/core/common/net/destination.proto", fileDescriptor1) }
var fileDescriptor1 = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x2e, 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, 0x49, 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0x2c, 0xc9, 0xcc,
0xcf, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x85, 0x29, 0x2e, 0x4a, 0xd5, 0x83, 0x28,
0xd4, 0xcb, 0x4b, 0x2d, 0x91, 0x52, 0xc7, 0x6d, 0x46, 0x5e, 0x6a, 0x49, 0x79, 0x7e, 0x51, 0x36,
0x44, 0x3f, 0x3e, 0x85, 0x89, 0x29, 0x29, 0x45, 0xa9, 0xc5, 0xc5, 0x10, 0x85, 0x4a, 0x33, 0x19,
0xb9, 0x78, 0x5d, 0x10, 0xd6, 0x07, 0x38, 0x09, 0x59, 0x70, 0xb1, 0x43, 0xcd, 0x92, 0x60, 0x54,
0x60, 0xd4, 0xe0, 0x33, 0x92, 0xd3, 0xc3, 0xea, 0x18, 0x3d, 0x3f, 0x88, 0xaa, 0x20, 0x98, 0x72,
0x21, 0x2b, 0x2e, 0x76, 0xa8, 0xe1, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0x0a, 0x38, 0x74,
0x3a, 0x42, 0x54, 0x05, 0x38, 0x05, 0xc1, 0x34, 0x08, 0x09, 0x71, 0xb1, 0x14, 0xe4, 0x17, 0x95,
0x48, 0x30, 0x2b, 0x30, 0x6a, 0xf0, 0x06, 0x81, 0xd9, 0x4e, 0x46, 0x5c, 0x92, 0xc9, 0xf9, 0xb9,
0xd8, 0xcd, 0x70, 0x12, 0x40, 0x76, 0x35, 0xc8, 0x2b, 0x51, 0xcc, 0x79, 0xa9, 0x25, 0x49, 0x6c,
0x60, 0x6f, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe2, 0xd7, 0x78, 0x9a, 0x6e, 0x01, 0x00,
0x00,
// 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,
}

View File

@@ -8,8 +8,8 @@ option java_outer_classname = "DestinationProto";
import "v2ray.com/core/common/net/network.proto";
import "v2ray.com/core/common/net/address.proto";
message DestinationPB {
message Endpoint {
Network network = 1;
AddressPB address = 2;
IPOrDomain address = 2;
uint32 port = 3;
}

View File

@@ -13,12 +13,8 @@ type IPNet struct {
}
func NewIPNet() *IPNet {
return NewIPNetInitialValue(make(map[uint32]byte, 1024))
}
func NewIPNetInitialValue(data map[uint32]byte) *IPNet {
return &IPNet{
cache: data,
cache: make(map[uint32]byte, 1024),
}
}
@@ -45,11 +41,15 @@ func (this *IPNet) Add(ipNet *net.IPNet) {
// For now, we don't support IPv6
return
}
value := ipToUint32(ipv4)
mask := ipMaskToByte(ipNet.Mask)
existing, found := this.cache[value]
this.AddIP(ipv4, mask)
}
func (this *IPNet) AddIP(ip []byte, mask byte) {
k := ipToUint32(ip)
existing, found := this.cache[k]
if !found || existing > mask {
this.cache[value] = mask
this.cache[k] = mask
}
}
@@ -61,7 +61,7 @@ func (this *IPNet) Contains(ip net.IP) bool {
originalValue := ipToUint32(ipv4)
if entry, found := this.cache[originalValue]; found {
if entry == 0 {
if entry == 32 {
return true
}
}
@@ -80,12 +80,8 @@ func (this *IPNet) Contains(ip net.IP) bool {
return false
}
func (this *IPNet) Serialize() []uint32 {
content := make([]uint32, 0, 2*len(this.cache))
for key, value := range this.cache {
content = append(content, uint32(key), uint32(value))
}
return content
func (this *IPNet) IsEmpty() bool {
return len(this.cache) == 0
}
func init() {

View File

@@ -2,8 +2,6 @@ package net
import (
"strings"
"v2ray.com/core/common/collect"
)
func ParseNetwork(nwStr string) Network {
@@ -56,17 +54,6 @@ func (this Network) UrlPrefix() string {
}
}
// NewNetworkList construsts a NetWorklist from the given StringListeralList.
func NewNetworkList(networks collect.StringList) *NetworkList {
list := &NetworkList{
Network: make([]Network, networks.Len()),
}
for idx, network := range networks {
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.Network {

View File

@@ -16,8 +16,10 @@ var _ = math.Inf
type Network int32
const (
Network_Unknown Network = 0
Network_RawTCP Network = 1
Network_Unknown Network = 0
// Native TCP provided by system.
Network_RawTCP Network = 1
// V2Ray specific TCP.
Network_TCP Network = 2
Network_UDP Network = 3
Network_KCP Network = 4

View File

@@ -7,10 +7,17 @@ option java_outer_classname = "NetworkProto";
enum Network {
Unknown = 0;
// Native TCP provided by system.
RawTCP = 1;
// V2Ray specific TCP.
TCP = 2;
UDP = 3;
KCP = 4;
WebSocket = 5;
}

View File

@@ -1,27 +0,0 @@
// +build json
package net
import (
"encoding/json"
"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)
return nil
}

View File

@@ -1,48 +0,0 @@
// +build json
package net_test
import (
"encoding/json"
"testing"
. "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(ParseNetwork("tcp"))).IsTrue()
assert.Bool(list.HasNetwork(ParseNetwork("udp"))).IsFalse()
}
func TestStringNetworkList(t *testing.T) {
assert := assert.On(t)
var list NetworkList
err := json.Unmarshal([]byte("\"TCP, ip\""), &list)
assert.Error(err).IsNil()
assert.Bool(list.HasNetwork(ParseNetwork("tcp"))).IsTrue()
assert.Bool(list.HasNetwork(ParseNetwork("udp"))).IsFalse()
}
func TestInvalidNetworkJson(t *testing.T) {
assert := assert.On(t)
var list NetworkList
err := json.Unmarshal([]byte("0"), &list)
assert.Error(err).IsNotNil()
}

View File

@@ -15,8 +15,8 @@ var _ = math.Inf
// PortRange represents a range of ports.
type PortRange struct {
From uint32 `protobuf:"varint,1,opt,name=From,json=from" json:"From,omitempty"`
To uint32 `protobuf:"varint,2,opt,name=To,json=to" json:"To,omitempty"`
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{} }
@@ -31,15 +31,14 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/common/net/port.proto", fileDescriptor3) }
var fileDescriptor3 = []byte{
// 148 bytes of a gzipped FileDescriptorProto
// 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, 0x62, 0x49, 0x2b, 0xca, 0xcf, 0x15, 0xe2,
0xe3, 0x62, 0x0a, 0xc9, 0x97, 0x60, 0x02, 0x8b, 0x30, 0x95, 0xe4, 0x3b, 0x69, 0x73, 0x49, 0x26,
0xe7, 0xe7, 0xea, 0x61, 0x35, 0xcd, 0x09, 0x6c, 0x56, 0x00, 0xc8, 0xbe, 0x28, 0xe6, 0xbc, 0xd4,
0x92, 0x24, 0x36, 0xb0, 0xdd, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x28, 0x7b, 0x9b, 0xb3,
0xa3, 0x00, 0x00, 0x00,
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,
}

View File

@@ -1,69 +0,0 @@
// +build json
package net
import (
"encoding/json"
"strings"
"v2ray.com/core/common/log"
)
func parseIntPort(data []byte) (Port, error) {
var intPort uint32
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 = uint32(port)
this.To = uint32(port)
return nil
}
from, to, err := parseStringPort(data)
if err == nil {
this.From = uint32(from)
this.To = uint32(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
}

View File

@@ -1,72 +0,0 @@
// +build json
package net_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/common/net"
"v2ray.com/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.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(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.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(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.Uint32(portRange.From).Equals(1234)
assert.Uint32(portRange.To).Equals(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)
}

View File

@@ -0,0 +1,39 @@
package predicate
type Predicate func() bool
func (this Predicate) And(predicate Predicate) Predicate {
return All(this, predicate)
}
func (this Predicate) Or(predicate Predicate) Predicate {
return Any(this, predicate)
}
func All(predicates ...Predicate) Predicate {
return func() bool {
for _, p := range predicates {
if !p() {
return false
}
}
return true
}
}
func Any(predicates ...Predicate) Predicate {
return func() bool {
for _, p := range predicates {
if p() {
return true
}
}
return false
}
}
func Not(predicate Predicate) Predicate {
return func() bool {
return !predicate()
}
}

View File

@@ -13,9 +13,9 @@ func TestServerList(t *testing.T) {
assert := assert.On(t)
list := NewServerList()
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
assert.Uint32(list.Size()).Equals(1)
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
assert.Uint32(list.Size()).Equals(2)
server := list.GetServer(1)
@@ -32,9 +32,9 @@ func TestServerPicker(t *testing.T) {
assert := assert.On(t)
list := NewServerList()
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(nil, v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(3)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(3)), BeforeTime(time.Now().Add(time.Second))))
picker := NewRoundRobinServerPicker(list)
server := picker.PickServer()

View File

@@ -45,24 +45,22 @@ func (this *TimeoutValidStrategy) Invalidate() {
type ServerSpec struct {
sync.RWMutex
dest v2net.Destination
users []*User
valid ValidationStrategy
newAccount NewAccountFactory
dest v2net.Destination
users []*User
valid ValidationStrategy
}
func NewServerSpec(newAccount NewAccountFactory, dest v2net.Destination, valid ValidationStrategy, users ...*User) *ServerSpec {
func NewServerSpec(dest v2net.Destination, valid ValidationStrategy, users ...*User) *ServerSpec {
return &ServerSpec{
dest: dest,
users: users,
valid: valid,
newAccount: newAccount,
dest: dest,
users: users,
valid: valid,
}
}
func NewServerSpecFromPB(newAccount NewAccountFactory, spec ServerSpecPB) *ServerSpec {
func NewServerSpecFromPB(spec ServerEndpoint) *ServerSpec {
dest := v2net.TCPDestination(spec.Address.AsAddress(), v2net.Port(spec.Port))
return NewServerSpec(newAccount, dest, AlwaysValid(), spec.User...)
return NewServerSpec(dest, AlwaysValid(), spec.User...)
}
func (this *ServerSpec) Destination() v2net.Destination {
@@ -73,12 +71,12 @@ func (this *ServerSpec) HasUser(user *User) bool {
this.RLock()
defer this.RUnlock()
accountA, err := user.GetTypedAccount(this.newAccount())
accountA, err := user.GetTypedAccount()
if err != nil {
return false
}
for _, u := range this.users {
accountB, err := u.GetTypedAccount(this.newAccount())
accountB, err := u.GetTypedAccount()
if err == nil && accountA.Equals(accountB) {
return true
}

View File

@@ -10,7 +10,7 @@ It is generated from these files:
v2ray.com/core/common/protocol/user.proto
It has these top-level messages:
ServerSpecPB
ServerEndpoint
User
*/
package protocol
@@ -31,25 +31,25 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type ServerSpecPB struct {
Address *v2ray_core_common_net.AddressPB `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
Port uint32 `protobuf:"varint,2,opt,name=port" json:"port,omitempty"`
User []*User `protobuf:"bytes,3,rep,name=user" json:"user,omitempty"`
type ServerEndpoint struct {
Address *v2ray_core_common_net.IPOrDomain `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
Port uint32 `protobuf:"varint,2,opt,name=port" json:"port,omitempty"`
User []*User `protobuf:"bytes,3,rep,name=user" json:"user,omitempty"`
}
func (m *ServerSpecPB) Reset() { *m = ServerSpecPB{} }
func (m *ServerSpecPB) String() string { return proto.CompactTextString(m) }
func (*ServerSpecPB) ProtoMessage() {}
func (*ServerSpecPB) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *ServerEndpoint) Reset() { *m = ServerEndpoint{} }
func (m *ServerEndpoint) String() string { return proto.CompactTextString(m) }
func (*ServerEndpoint) ProtoMessage() {}
func (*ServerEndpoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *ServerSpecPB) GetAddress() *v2ray_core_common_net.AddressPB {
func (m *ServerEndpoint) GetAddress() *v2ray_core_common_net.IPOrDomain {
if m != nil {
return m.Address
}
return nil
}
func (m *ServerSpecPB) GetUser() []*User {
func (m *ServerEndpoint) GetUser() []*User {
if m != nil {
return m.User
}
@@ -57,25 +57,26 @@ func (m *ServerSpecPB) GetUser() []*User {
}
func init() {
proto.RegisterType((*ServerSpecPB)(nil), "v2ray.core.common.protocol.ServerSpecPB")
proto.RegisterType((*ServerEndpoint)(nil), "v2ray.core.common.protocol.ServerEndpoint")
}
func init() { proto.RegisterFile("v2ray.com/core/common/protocol/server_spec.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 216 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8e, 0x3f, 0x4b, 0xc7, 0x30,
0x10, 0x86, 0x89, 0xbf, 0xa2, 0x12, 0x15, 0x21, 0x53, 0xe9, 0x20, 0xc1, 0xc5, 0xba, 0x24, 0x52,
0x9d, 0x74, 0x32, 0x9f, 0xa0, 0xb4, 0xb8, 0xb8, 0x48, 0x4d, 0x6f, 0x33, 0xbd, 0x70, 0x89, 0x05,
0xbf, 0x87, 0x1f, 0x58, 0x9a, 0x18, 0x10, 0xfc, 0xb7, 0x1d, 0x77, 0xcf, 0xbd, 0xef, 0xc3, 0xaf,
0xd6, 0x8e, 0xa6, 0x37, 0x65, 0xd1, 0x69, 0x8b, 0x04, 0xda, 0xa2, 0x73, 0xb8, 0x68, 0x4f, 0x18,
0xd1, 0xe2, 0x8b, 0x0e, 0x40, 0x2b, 0xd0, 0x53, 0xf0, 0x60, 0x55, 0x5a, 0x8a, 0xa6, 0x7c, 0x10,
0xa8, 0x4c, 0xab, 0x42, 0x37, 0x17, 0x3f, 0xa7, 0x2d, 0x10, 0xf5, 0x34, 0xcf, 0x04, 0x21, 0x64,
0xb6, 0xb9, 0xfc, 0xa7, 0xf6, 0x35, 0x00, 0x65, 0xf4, 0xfc, 0x9d, 0xf1, 0xe3, 0x31, 0x59, 0x8c,
0x1e, 0x6c, 0x6f, 0xc4, 0x2d, 0x3f, 0xf8, 0x0c, 0xab, 0x99, 0x64, 0xed, 0x51, 0x27, 0xd5, 0x77,
0xa5, 0x05, 0xa2, 0xba, 0xcf, 0x54, 0x6f, 0x86, 0xf2, 0x20, 0x04, 0xaf, 0x3c, 0x52, 0xac, 0xf7,
0x24, 0x6b, 0x4f, 0x86, 0x34, 0x8b, 0x1b, 0x5e, 0x6d, 0x75, 0xf5, 0x4e, 0xee, 0x7e, 0x09, 0x2b,
0x5a, 0xea, 0x21, 0x00, 0x0d, 0x89, 0x36, 0x77, 0xfc, 0xcc, 0xa2, 0xfb, 0x03, 0x36, 0xa7, 0x5f,
0xac, 0xb7, 0xdd, 0xe3, 0x61, 0x39, 0x3d, 0xef, 0xa7, 0xe9, 0xfa, 0x23, 0x00, 0x00, 0xff, 0xff,
0x30, 0xc6, 0x1e, 0xae, 0x7e, 0x01, 0x00, 0x00,
// 230 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0x3d, 0x4b, 0x04, 0x31,
0x10, 0x86, 0x59, 0xef, 0x50, 0xc9, 0xa1, 0x42, 0xaa, 0x65, 0x0b, 0x89, 0x36, 0xae, 0xcd, 0x44,
0x56, 0xbb, 0xeb, 0x0e, 0x2d, 0xac, 0x3c, 0xf6, 0xb0, 0xb1, 0x91, 0x35, 0x3b, 0xc5, 0x81, 0xc9,
0x84, 0x49, 0x3c, 0xf0, 0x97, 0xf8, 0x77, 0x65, 0x13, 0x53, 0xf9, 0xd5, 0x0d, 0x6f, 0x9e, 0xf7,
0x23, 0xe2, 0x6a, 0xd7, 0xf1, 0xf0, 0x0e, 0x86, 0xac, 0x36, 0xc4, 0xa8, 0x0d, 0x59, 0x4b, 0x4e,
0x7b, 0xa6, 0x48, 0x86, 0x5e, 0x75, 0x40, 0xde, 0x21, 0x3f, 0x07, 0x8f, 0x06, 0x92, 0x28, 0x9b,
0xe2, 0x60, 0x84, 0x4c, 0x43, 0xa1, 0x9b, 0x8b, 0x9f, 0xd3, 0x1c, 0x46, 0x3d, 0x8c, 0x23, 0x63,
0x08, 0x99, 0x6d, 0x2e, 0xff, 0xa9, 0x7d, 0x0b, 0xc8, 0x19, 0x3d, 0xff, 0xa8, 0xc4, 0xf1, 0x26,
0xad, 0xb8, 0x73, 0xa3, 0xa7, 0xad, 0x8b, 0x72, 0x29, 0x0e, 0xbe, 0xe2, 0xea, 0x4a, 0x55, 0xed,
0xa2, 0x3b, 0x83, 0xef, 0xa3, 0x1c, 0x46, 0xb8, 0x5f, 0x3f, 0xf0, 0x2d, 0xd9, 0x61, 0xeb, 0xfa,
0xe2, 0x90, 0x52, 0xcc, 0x3d, 0x71, 0xac, 0xf7, 0x54, 0xd5, 0x1e, 0xf5, 0xe9, 0x96, 0x37, 0x62,
0x3e, 0x35, 0xd6, 0x33, 0x35, 0x6b, 0x17, 0x9d, 0x82, 0xdf, 0xbf, 0x08, 0x8f, 0x01, 0xb9, 0x4f,
0xf4, 0x6a, 0x29, 0x4e, 0x0d, 0xd9, 0x3f, 0xe0, 0xd5, 0x49, 0x1e, 0xbe, 0xf1, 0x68, 0xd6, 0x93,
0xf6, 0x74, 0x58, 0x9e, 0x5e, 0xf6, 0xd3, 0x75, 0xfd, 0x19, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x28,
0xb3, 0x3a, 0x81, 0x01, 0x00, 0x00,
}

View File

@@ -8,8 +8,8 @@ option java_outer_classname = "ServerSpecProto";
import "v2ray.com/core/common/net/address.proto";
import "v2ray.com/core/common/protocol/user.proto";
message ServerSpecPB {
v2ray.core.common.net.AddressPB address = 1;
message ServerEndpoint {
v2ray.core.common.net.IPOrDomain address = 1;
uint32 port = 2;
repeated v2ray.core.common.protocol.User user = 3;
}

View File

@@ -2,31 +2,31 @@ package protocol
import (
"errors"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
)
var (
ErrUserMissing = errors.New("User is not specified.")
ErrAccountMissing = errors.New("Account is not specified.")
ErrNonMessageType = errors.New("Not a protobuf message.")
ErrUserMissing = errors.New("User is not specified.")
ErrAccountMissing = errors.New("Account is not specified.")
ErrNonMessageType = errors.New("Not a protobuf message.")
ErrUnknownAccountType = errors.New("Unknown account type.")
)
func (this *User) GetTypedAccount(account AsAccount) (Account, error) {
anyAccount := this.GetAccount()
if anyAccount == nil {
func (this *User) GetTypedAccount() (Account, error) {
if this.GetAccount() == nil {
return nil, ErrAccountMissing
}
protoAccount, ok := account.(proto.Message)
if !ok {
return nil, ErrNonMessageType
}
err := ptypes.UnmarshalAny(anyAccount, protoAccount)
rawAccount, err := this.Account.GetInstance()
if err != nil {
return nil, err
}
return account.AsAccount()
if asAccount, ok := rawAccount.(AsAccount); ok {
return asAccount.AsAccount()
}
if account, ok := rawAccount.(Account); ok {
return account, nil
}
return nil, errors.New("Unknown account type: " + this.Account.Type)
}
func (this *User) GetSettings() UserSettings {

View File

@@ -7,7 +7,7 @@ package protocol
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/golang/protobuf/ptypes/any"
import v2ray_core_common_loader "v2ray.com/core/common/loader"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@@ -15,9 +15,10 @@ var _ = fmt.Errorf
var _ = math.Inf
type User struct {
Level uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"`
Email string `protobuf:"bytes,2,opt,name=email" json:"email,omitempty"`
Account *google_protobuf.Any `protobuf:"bytes,3,opt,name=account" json:"account,omitempty"`
Level uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"`
Email string `protobuf:"bytes,2,opt,name=email" json:"email,omitempty"`
// Protocol specific account information.
Account *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,3,opt,name=account" json:"account,omitempty"`
}
func (m *User) Reset() { *m = User{} }
@@ -25,7 +26,7 @@ func (m *User) String() string { return proto.CompactTextString(m) }
func (*User) ProtoMessage() {}
func (*User) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
func (m *User) GetAccount() *google_protobuf.Any {
func (m *User) GetAccount() *v2ray_core_common_loader.TypedSettings {
if m != nil {
return m.Account
}
@@ -39,17 +40,18 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/common/protocol/user.proto", fileDescriptor1) }
var fileDescriptor1 = []byte{
// 192 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x8e, 0xbd, 0xea, 0xc2, 0x30,
0x14, 0xc5, 0xc9, 0xff, 0x43, 0x6d, 0xc4, 0xa5, 0x74, 0xa8, 0x1d, 0xa4, 0x38, 0xd5, 0xe5, 0x06,
0x2a, 0x3e, 0x80, 0x7d, 0x02, 0x29, 0xb8, 0xb8, 0xa5, 0xe1, 0x5a, 0x84, 0x24, 0x57, 0xd2, 0x0f,
0xe8, 0xdb, 0x4b, 0x1b, 0x32, 0xba, 0xe5, 0x77, 0xf2, 0xbb, 0x9c, 0xc3, 0x4f, 0x63, 0xe9, 0xe4,
0x04, 0x8a, 0x8c, 0x50, 0xe4, 0x50, 0x28, 0x32, 0x86, 0xac, 0x78, 0x3b, 0xea, 0x49, 0x91, 0x16,
0x43, 0x87, 0x0e, 0x16, 0x8a, 0xb3, 0xa0, 0x3a, 0x04, 0xaf, 0x41, 0xd0, 0xb2, 0x7d, 0x4b, 0xd4,
0x6a, 0xf4, 0x77, 0xcd, 0xf0, 0x14, 0xd2, 0x4e, 0xfe, 0xf7, 0xd8, 0xf0, 0xbf, 0x7b, 0x87, 0x2e,
0x4e, 0xf8, 0xbf, 0xc6, 0x11, 0x75, 0xca, 0x72, 0x56, 0xec, 0x6a, 0x0f, 0x73, 0x8a, 0x46, 0xbe,
0x74, 0xfa, 0x93, 0xb3, 0x22, 0xaa, 0x3d, 0xc4, 0xc0, 0xd7, 0x52, 0x29, 0x1a, 0x6c, 0x9f, 0xfe,
0xe6, 0xac, 0xd8, 0x96, 0x09, 0xf8, 0x02, 0x08, 0x05, 0x70, 0xb5, 0x53, 0x1d, 0xa4, 0xea, 0xc2,
0x0f, 0x8a, 0x0c, 0x7c, 0x1f, 0x58, 0x45, 0xf3, 0x86, 0xdb, 0x4c, 0x8f, 0x4d, 0x08, 0x9b, 0xd5,
0xf2, 0x3a, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xd8, 0xfc, 0x46, 0xc6, 0x05, 0x01, 0x00, 0x00,
// 200 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x8f, 0x3f, 0xef, 0x82, 0x30,
0x10, 0x86, 0xd3, 0xdf, 0x5f, 0xa9, 0x71, 0x21, 0x0e, 0x84, 0xc1, 0x10, 0x17, 0x70, 0x69, 0x13,
0x8c, 0x1f, 0x40, 0x3e, 0x81, 0x41, 0x5d, 0xdc, 0x6a, 0xb9, 0x18, 0x92, 0x96, 0x23, 0xa5, 0x90,
0xf0, 0xed, 0x0d, 0x34, 0x9d, 0xd4, 0xad, 0xcf, 0x9b, 0xa7, 0x77, 0xef, 0xd1, 0xdd, 0x90, 0x1b,
0x31, 0x32, 0x89, 0x9a, 0x4b, 0x34, 0xc0, 0x25, 0x6a, 0x8d, 0x0d, 0x6f, 0x0d, 0x5a, 0x94, 0xa8,
0x78, 0xdf, 0x81, 0x61, 0x33, 0x85, 0xb1, 0x57, 0x0d, 0x30, 0xa7, 0x31, 0xaf, 0xc5, 0xe9, 0xfb,
0x31, 0x0a, 0x45, 0x05, 0x86, 0xdb, 0xb1, 0x05, 0xe7, 0x6e, 0x7b, 0xfa, 0x73, 0xed, 0xc0, 0x84,
0x6b, 0xfa, 0xab, 0x60, 0x00, 0x15, 0x91, 0x84, 0x64, 0xab, 0xd2, 0xc1, 0x94, 0x82, 0x16, 0xb5,
0x8a, 0xbe, 0x12, 0x92, 0x05, 0xa5, 0x83, 0xf0, 0x48, 0xff, 0x85, 0x94, 0xd8, 0x37, 0x36, 0xfa,
0x4e, 0x48, 0xb6, 0xcc, 0x53, 0xf6, 0x5a, 0xc5, 0xad, 0x62, 0x97, 0xb1, 0x85, 0xea, 0x0c, 0xd6,
0xd6, 0xcd, 0xa3, 0x2b, 0xfd, 0xbf, 0xe2, 0x40, 0x37, 0x12, 0x35, 0xfb, 0x7c, 0x41, 0x11, 0x4c,
0xb5, 0x4e, 0x13, 0xdd, 0x16, 0x3e, 0xbc, 0xff, 0xcd, 0xaf, 0xfd, 0x33, 0x00, 0x00, 0xff, 0xff,
0x68, 0x83, 0xed, 0x6b, 0x26, 0x01, 0x00, 0x00,
}

View File

@@ -5,10 +5,12 @@ option go_package = "protocol";
option java_package = "com.v2ray.core.common.protocol";
option java_outer_classname = "UserProto";
import "google/protobuf/any.proto";
import "v2ray.com/core/common/loader/type.proto";
message User {
uint32 level = 1;
string email = 2;
google.protobuf.Any account = 3;
// Protocol specific account information.
v2ray.core.common.loader.TypedSettings account = 3;
}

View File

@@ -1,21 +0,0 @@
// +build json
package protocol
import "encoding/json"
func (u *User) UnmarshalJSON(data []byte) error {
type rawUser struct {
EmailString string `json:"email"`
LevelByte byte `json:"level"`
}
var rawUserValue rawUser
if err := json.Unmarshal(data, &rawUserValue); err != nil {
return err
}
u.Email = rawUserValue.EmailString
u.Level = uint32(rawUserValue.LevelByte)
return nil
}

View File

@@ -1,34 +0,0 @@
// +build json
package protocol_test
import (
"encoding/json"
"testing"
. "v2ray.com/core/common/protocol"
"v2ray.com/core/testing/assert"
)
func TestUserParsing(t *testing.T) {
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{
"id": "96edb838-6d68-42ef-a933-25f7ac3a9d09",
"email": "love@v2ray.com",
"level": 1,
"alterId": 100
}`), user)
assert.Error(err).IsNil()
assert.Byte(byte(user.Level)).Equals(1)
assert.String(user.Email).Equals("love@v2ray.com")
}
func TestInvalidUserJson(t *testing.T) {
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{"email": 1234}`), user)
assert.Error(err).IsNotNil()
}

View File

@@ -16,34 +16,43 @@ type Strategy interface {
}
type retryer struct {
NextDelay func(int) int
totalAttempt int
nextDelay func() uint32
}
// On implements Strategy.On.
func (r *retryer) On(method func() error) error {
attempt := 0
for {
for attempt < r.totalAttempt {
err := method()
if err == nil {
return nil
}
delay := r.NextDelay(attempt)
if delay < 0 {
return ErrRetryFailed
}
delay := r.nextDelay()
<-time.After(time.Duration(delay) * time.Millisecond)
attempt++
}
return ErrRetryFailed
}
// Timed returns a retry strategy with fixed interval.
func Timed(attempts int, delay int) Strategy {
func Timed(attempts int, delay uint32) Strategy {
return &retryer{
NextDelay: func(attempt int) int {
if attempt >= attempts {
return -1
}
totalAttempt: attempts,
nextDelay: func() uint32 {
return delay
},
}
}
func ExponentialBackoff(attempts int, delay uint32) Strategy {
nextDelay := uint32(0)
return &retryer{
totalAttempt: attempts,
nextDelay: func() uint32 {
r := nextDelay
nextDelay += delay
return r
},
}
}

View File

@@ -68,14 +68,26 @@ func TestRetryExhausted(t *testing.T) {
startTime := time.Now()
called := 0
err := Timed(2, 1000).On(func() error {
if called < 5 {
called++
return errorTestOnly
}
return nil
called++
return errorTestOnly
})
duration := time.Since(startTime)
assert.Error(err).Equals(ErrRetryFailed)
assert.Int64(int64(duration / time.Millisecond)).AtLeast(1900)
}
func TestExponentialBackoff(t *testing.T) {
assert := assert.On(t)
startTime := time.Now()
called := 0
err := ExponentialBackoff(10, 100).On(func() error {
called++
return errorTestOnly
})
duration := time.Since(startTime)
assert.Error(err).Equals(ErrRetryFailed)
assert.Int64(int64(duration / time.Millisecond)).AtLeast(4000)
}

View File

@@ -1,35 +1,51 @@
package signal
import (
"sync"
)
// CancelSignal is a signal passed to goroutine, in order to cancel the goroutine on demand.
type CancelSignal struct {
cancel chan struct{}
done chan struct{}
done sync.WaitGroup
}
// NewCloseSignal creates a new CancelSignal.
func NewCloseSignal() *CancelSignal {
return &CancelSignal{
cancel: make(chan struct{}),
done: make(chan struct{}),
}
}
func (this *CancelSignal) WaitThread() {
this.done.Add(1)
}
// Cancel signals the goroutine to stop.
func (this *CancelSignal) Cancel() {
close(this.cancel)
}
func (this *CancelSignal) Cancelled() bool {
select {
case <-this.cancel:
return true
default:
return false
}
}
// WaitForCancel should be monitored by the goroutine for when to stop.
func (this *CancelSignal) WaitForCancel() <-chan struct{} {
return this.cancel
}
// Done signals the caller that the goroutine has completely finished.
func (this *CancelSignal) Done() {
close(this.done)
// FinishThread signals that current goroutine has finished.
func (this *CancelSignal) FinishThread() {
this.done.Done()
}
// WaitForDone is used by caller to wait for the goroutine finishes.
func (this *CancelSignal) WaitForDone() <-chan struct{} {
return this.done
func (this *CancelSignal) WaitForDone() {
this.done.Wait()
}

55
config.go Normal file
View File

@@ -0,0 +1,55 @@
package core
import (
"v2ray.com/core/common"
v2net "v2ray.com/core/common/net"
)
func (this *AllocationStrategyConcurrency) GetValue() uint32 {
if this == nil {
return 3
}
return this.Value
}
func (this *AllocationStrategyRefresh) GetValue() uint32 {
if this == nil {
return 5
}
return this.Value
}
func (this *InboundConnectionConfig) GetAllocationStrategyValue() *AllocationStrategy {
if this.AllocationStrategy == nil {
return &AllocationStrategy{}
}
return this.AllocationStrategy
}
func (this *InboundConnectionConfig) GetListenOnValue() v2net.Address {
if this.GetListenOn() == nil {
return v2net.AnyIP
}
return this.ListenOn.AsAddress()
}
func (this *InboundConnectionConfig) GetTypedSettings() (interface{}, error) {
if this.GetSettings() == nil {
return nil, common.ErrBadConfiguration
}
return this.GetSettings().GetInstance()
}
func (this *OutboundConnectionConfig) GetTypedSettings() (interface{}, error) {
if this.GetSettings() == nil {
return nil, common.ErrBadConfiguration
}
return this.GetSettings().GetInstance()
}
func (this *OutboundConnectionConfig) GetSendThroughValue() v2net.Address {
if this.GetSendThrough() == nil {
return v2net.AnyIP
}
return this.SendThrough.AsAddress()
}

347
config.pb.go Normal file
View File

@@ -0,0 +1,347 @@
// Code generated by protoc-gen-go.
// source: v2ray.com/core/config.proto
// DO NOT EDIT!
/*
Package core is a generated protocol buffer package.
It is generated from these files:
v2ray.com/core/config.proto
It has these top-level messages:
AllocationStrategyConcurrency
AllocationStrategyRefresh
AllocationStrategy
InboundConnectionConfig
OutboundConnectionConfig
Config
*/
package core
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import v2ray_core_common_loader "v2ray.com/core/common/loader"
import v2ray_core_common_net "v2ray.com/core/common/net"
import v2ray_core_common_net1 "v2ray.com/core/common/net"
import v2ray_core_common_log "v2ray.com/core/common/log"
import v2ray_core_transport_internet "v2ray.com/core/transport/internet"
import v2ray_core_transport "v2ray.com/core/transport"
// 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
// Configuration serialization format.
type ConfigFormat int32
const (
ConfigFormat_Protobuf ConfigFormat = 0
ConfigFormat_JSON ConfigFormat = 1
)
var ConfigFormat_name = map[int32]string{
0: "Protobuf",
1: "JSON",
}
var ConfigFormat_value = map[string]int32{
"Protobuf": 0,
"JSON": 1,
}
func (x ConfigFormat) String() string {
return proto.EnumName(ConfigFormat_name, int32(x))
}
func (ConfigFormat) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type AllocationStrategy_Type int32
const (
// Always allocate all connection handlers.
AllocationStrategy_Always AllocationStrategy_Type = 0
// Randomly allocate specific range of handlers.
AllocationStrategy_Random AllocationStrategy_Type = 1
// External. Not supported yet.
AllocationStrategy_External AllocationStrategy_Type = 2
)
var AllocationStrategy_Type_name = map[int32]string{
0: "Always",
1: "Random",
2: "External",
}
var AllocationStrategy_Type_value = map[string]int32{
"Always": 0,
"Random": 1,
"External": 2,
}
func (x AllocationStrategy_Type) String() string {
return proto.EnumName(AllocationStrategy_Type_name, int32(x))
}
func (AllocationStrategy_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} }
type AllocationStrategyConcurrency struct {
Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
}
func (m *AllocationStrategyConcurrency) Reset() { *m = AllocationStrategyConcurrency{} }
func (m *AllocationStrategyConcurrency) String() string { return proto.CompactTextString(m) }
func (*AllocationStrategyConcurrency) ProtoMessage() {}
func (*AllocationStrategyConcurrency) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type AllocationStrategyRefresh struct {
Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"`
}
func (m *AllocationStrategyRefresh) Reset() { *m = AllocationStrategyRefresh{} }
func (m *AllocationStrategyRefresh) String() string { return proto.CompactTextString(m) }
func (*AllocationStrategyRefresh) ProtoMessage() {}
func (*AllocationStrategyRefresh) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type AllocationStrategy struct {
Type AllocationStrategy_Type `protobuf:"varint,1,opt,name=type,enum=v2ray.core.AllocationStrategy_Type" json:"type,omitempty"`
// Number of handlers (ports) running in parallel.
// Default value is 3 if unset.
Concurrency *AllocationStrategyConcurrency `protobuf:"bytes,2,opt,name=concurrency" json:"concurrency,omitempty"`
// Number of minutes before a handler is regenerated.
// Default value is 5 if unset.
Refresh *AllocationStrategyRefresh `protobuf:"bytes,3,opt,name=refresh" json:"refresh,omitempty"`
}
func (m *AllocationStrategy) Reset() { *m = AllocationStrategy{} }
func (m *AllocationStrategy) String() string { return proto.CompactTextString(m) }
func (*AllocationStrategy) ProtoMessage() {}
func (*AllocationStrategy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *AllocationStrategy) GetConcurrency() *AllocationStrategyConcurrency {
if m != nil {
return m.Concurrency
}
return nil
}
func (m *AllocationStrategy) GetRefresh() *AllocationStrategyRefresh {
if m != nil {
return m.Refresh
}
return nil
}
// Config for an inbound connection handler.
type InboundConnectionConfig struct {
// Protocol specific settings. Must be one of the supported protocols.
Settings *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,1,opt,name=settings" json:"settings,omitempty"`
// Range of port number to run on. Both inclusive.
PortRange *v2ray_core_common_net.PortRange `protobuf:"bytes,2,opt,name=port_range,json=portRange" json:"port_range,omitempty"`
// IP address to listen on. 0.0.0.0 if unset.
ListenOn *v2ray_core_common_net1.IPOrDomain `protobuf:"bytes,3,opt,name=listen_on,json=listenOn" json:"listen_on,omitempty"`
// Tag of this handler.
Tag string `protobuf:"bytes,4,opt,name=tag" json:"tag,omitempty"`
AllocationStrategy *AllocationStrategy `protobuf:"bytes,5,opt,name=allocation_strategy,json=allocationStrategy" json:"allocation_strategy,omitempty"`
StreamSettings *v2ray_core_transport_internet.StreamConfig `protobuf:"bytes,6,opt,name=stream_settings,json=streamSettings" json:"stream_settings,omitempty"`
AllowPassiveConnection bool `protobuf:"varint,7,opt,name=allow_passive_connection,json=allowPassiveConnection" json:"allow_passive_connection,omitempty"`
}
func (m *InboundConnectionConfig) Reset() { *m = InboundConnectionConfig{} }
func (m *InboundConnectionConfig) String() string { return proto.CompactTextString(m) }
func (*InboundConnectionConfig) ProtoMessage() {}
func (*InboundConnectionConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *InboundConnectionConfig) GetSettings() *v2ray_core_common_loader.TypedSettings {
if m != nil {
return m.Settings
}
return nil
}
func (m *InboundConnectionConfig) GetPortRange() *v2ray_core_common_net.PortRange {
if m != nil {
return m.PortRange
}
return nil
}
func (m *InboundConnectionConfig) GetListenOn() *v2ray_core_common_net1.IPOrDomain {
if m != nil {
return m.ListenOn
}
return nil
}
func (m *InboundConnectionConfig) GetAllocationStrategy() *AllocationStrategy {
if m != nil {
return m.AllocationStrategy
}
return nil
}
func (m *InboundConnectionConfig) GetStreamSettings() *v2ray_core_transport_internet.StreamConfig {
if m != nil {
return m.StreamSettings
}
return nil
}
// Config for an outbound connection handler.
type OutboundConnectionConfig struct {
Settings *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,1,opt,name=settings" json:"settings,omitempty"`
// IP address to send data through. 0.0.0.0 if unset.
SendThrough *v2ray_core_common_net1.IPOrDomain `protobuf:"bytes,2,opt,name=send_through,json=sendThrough" json:"send_through,omitempty"`
StreamSettings *v2ray_core_transport_internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings" json:"stream_settings,omitempty"`
ProxySettings *v2ray_core_transport_internet.ProxyConfig `protobuf:"bytes,5,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"`
Tag string `protobuf:"bytes,4,opt,name=tag" json:"tag,omitempty"`
}
func (m *OutboundConnectionConfig) Reset() { *m = OutboundConnectionConfig{} }
func (m *OutboundConnectionConfig) String() string { return proto.CompactTextString(m) }
func (*OutboundConnectionConfig) ProtoMessage() {}
func (*OutboundConnectionConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *OutboundConnectionConfig) GetSettings() *v2ray_core_common_loader.TypedSettings {
if m != nil {
return m.Settings
}
return nil
}
func (m *OutboundConnectionConfig) GetSendThrough() *v2ray_core_common_net1.IPOrDomain {
if m != nil {
return m.SendThrough
}
return nil
}
func (m *OutboundConnectionConfig) GetStreamSettings() *v2ray_core_transport_internet.StreamConfig {
if m != nil {
return m.StreamSettings
}
return nil
}
func (m *OutboundConnectionConfig) GetProxySettings() *v2ray_core_transport_internet.ProxyConfig {
if m != nil {
return m.ProxySettings
}
return nil
}
type Config struct {
// Inbound handler configurations. Must have at least one item.
Inbound []*InboundConnectionConfig `protobuf:"bytes,1,rep,name=inbound" json:"inbound,omitempty"`
// Outbound handler configurations. Must have at least one item. The first item is used as default for routing.
Outbound []*OutboundConnectionConfig `protobuf:"bytes,2,rep,name=outbound" json:"outbound,omitempty"`
Log *v2ray_core_common_log.Config `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"`
// App configuration. Must be one in the app directory.
App []*v2ray_core_common_loader.TypedSettings `protobuf:"bytes,4,rep,name=app" json:"app,omitempty"`
Transport *v2ray_core_transport.Config `protobuf:"bytes,5,opt,name=transport" json:"transport,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{5} }
func (m *Config) GetInbound() []*InboundConnectionConfig {
if m != nil {
return m.Inbound
}
return nil
}
func (m *Config) GetOutbound() []*OutboundConnectionConfig {
if m != nil {
return m.Outbound
}
return nil
}
func (m *Config) GetLog() *v2ray_core_common_log.Config {
if m != nil {
return m.Log
}
return nil
}
func (m *Config) GetApp() []*v2ray_core_common_loader.TypedSettings {
if m != nil {
return m.App
}
return nil
}
func (m *Config) GetTransport() *v2ray_core_transport.Config {
if m != nil {
return m.Transport
}
return nil
}
func init() {
proto.RegisterType((*AllocationStrategyConcurrency)(nil), "v2ray.core.AllocationStrategyConcurrency")
proto.RegisterType((*AllocationStrategyRefresh)(nil), "v2ray.core.AllocationStrategyRefresh")
proto.RegisterType((*AllocationStrategy)(nil), "v2ray.core.AllocationStrategy")
proto.RegisterType((*InboundConnectionConfig)(nil), "v2ray.core.InboundConnectionConfig")
proto.RegisterType((*OutboundConnectionConfig)(nil), "v2ray.core.OutboundConnectionConfig")
proto.RegisterType((*Config)(nil), "v2ray.core.Config")
proto.RegisterEnum("v2ray.core.ConfigFormat", ConfigFormat_name, ConfigFormat_value)
proto.RegisterEnum("v2ray.core.AllocationStrategy_Type", AllocationStrategy_Type_name, AllocationStrategy_Type_value)
}
func init() { proto.RegisterFile("v2ray.com/core/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 719 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x95, 0xdd, 0x6e, 0xd3, 0x30,
0x1c, 0xc5, 0x97, 0xb6, 0xeb, 0xda, 0x7f, 0xb7, 0x52, 0x19, 0x04, 0x61, 0x30, 0x54, 0xba, 0xaf,
0x32, 0x50, 0x2a, 0x8a, 0x10, 0x1f, 0x12, 0x8c, 0xad, 0x03, 0x69, 0x20, 0xd1, 0xe2, 0xee, 0x8a,
0x9b, 0xca, 0x4b, 0xbd, 0x2c, 0x52, 0x62, 0x47, 0x8e, 0xbb, 0xad, 0x8f, 0xc0, 0xe3, 0xf0, 0x2a,
0x3c, 0x01, 0x8f, 0x82, 0xec, 0xb8, 0x69, 0x47, 0xdb, 0x6d, 0x12, 0xe2, 0x2e, 0x8d, 0xcf, 0xef,
0xd8, 0x39, 0xc7, 0x76, 0xe1, 0xc1, 0x59, 0x53, 0x90, 0xa1, 0xe3, 0xf2, 0xb0, 0xe1, 0x72, 0x41,
0x1b, 0x2e, 0x67, 0x27, 0xbe, 0xe7, 0x44, 0x82, 0x4b, 0x8e, 0x60, 0x34, 0x28, 0xe8, 0xea, 0xf6,
0x94, 0x30, 0x0c, 0x39, 0x6b, 0x04, 0x9c, 0xf4, 0xa9, 0x68, 0xc8, 0x61, 0x44, 0x13, 0x68, 0x75,
0x63, 0xb6, 0x90, 0x51, 0xd9, 0x88, 0xb8, 0x90, 0x46, 0xb5, 0x3d, 0x5f, 0x45, 0xfa, 0x7d, 0x41,
0xe3, 0xd8, 0x08, 0xb7, 0xe6, 0xcd, 0xeb, 0x5d, 0x5a, 0xeb, 0xaa, 0xf3, 0x97, 0x4e, 0x0a, 0xc2,
0x62, 0x35, 0x61, 0xc3, 0x67, 0x92, 0x0a, 0x65, 0x7c, 0x49, 0xbf, 0x39, 0x57, 0x3f, 0x29, 0xab,
0xbd, 0x84, 0xb5, 0xbd, 0x20, 0xe0, 0x2e, 0x91, 0x3e, 0x67, 0x5d, 0x29, 0x88, 0xa4, 0xde, 0xb0,
0xc5, 0x99, 0x3b, 0x10, 0x82, 0x32, 0x77, 0x88, 0xee, 0xc0, 0xe2, 0x19, 0x09, 0x06, 0xd4, 0xb6,
0xaa, 0x56, 0x7d, 0x05, 0x27, 0x3f, 0x6a, 0xcf, 0xe1, 0xfe, 0x34, 0x86, 0xe9, 0x89, 0xa0, 0xf1,
0xe9, 0x1c, 0xe4, 0x47, 0x06, 0xd0, 0x34, 0x83, 0x5e, 0x41, 0x4e, 0x85, 0xab, 0xb5, 0xe5, 0xe6,
0xba, 0x33, 0xae, 0xc4, 0x99, 0x56, 0x3b, 0x47, 0xc3, 0x88, 0x62, 0x0d, 0xa0, 0x2f, 0x50, 0x72,
0xc7, 0xeb, 0xb4, 0x33, 0x55, 0xab, 0x5e, 0x6a, 0x3e, 0xb9, 0x9a, 0x9f, 0xf8, 0x30, 0x3c, 0x49,
0xa3, 0x5d, 0x58, 0x12, 0xc9, 0xea, 0xed, 0xac, 0x36, 0xda, 0xbc, 0xda, 0xc8, 0x7c, 0x2a, 0x1e,
0x51, 0xb5, 0x67, 0x90, 0x53, 0x6b, 0x43, 0x00, 0xf9, 0xbd, 0xe0, 0x9c, 0x0c, 0xe3, 0xca, 0x82,
0x7a, 0xc6, 0x84, 0xf5, 0x79, 0x58, 0xb1, 0xd0, 0x32, 0x14, 0x3e, 0x5e, 0xa8, 0x9e, 0x48, 0x50,
0xc9, 0xd4, 0x7e, 0x65, 0xe1, 0xde, 0x21, 0x3b, 0xe6, 0x03, 0xd6, 0x6f, 0x71, 0xc6, 0xa8, 0xab,
0xbc, 0x5b, 0xba, 0x17, 0xd4, 0x82, 0x42, 0x4c, 0xa5, 0xf4, 0x99, 0x17, 0xeb, 0x50, 0x4a, 0xcd,
0xed, 0xc9, 0xb5, 0x24, 0xfb, 0xc3, 0x49, 0xf6, 0xa5, 0xce, 0xa3, 0xdf, 0x35, 0x72, 0x9c, 0x82,
0x68, 0x17, 0x40, 0x75, 0xdd, 0x13, 0x84, 0x79, 0xd4, 0x64, 0x53, 0x9d, 0x61, 0xc3, 0xa8, 0x74,
0x3a, 0x5c, 0x48, 0xac, 0x74, 0xb8, 0x18, 0x8d, 0x1e, 0xd1, 0x7b, 0x28, 0x06, 0x7e, 0x2c, 0x29,
0xeb, 0x71, 0x66, 0x22, 0x79, 0x3c, 0x87, 0x3f, 0xec, 0xb4, 0xc5, 0x01, 0x0f, 0x89, 0xcf, 0x70,
0x21, 0x61, 0xda, 0x0c, 0x55, 0x20, 0x2b, 0x89, 0x67, 0xe7, 0xaa, 0x56, 0xbd, 0x88, 0xd5, 0x23,
0x6a, 0xc3, 0x6d, 0x92, 0xe6, 0xd8, 0x8b, 0x4d, 0x90, 0xf6, 0xa2, 0xf6, 0x7e, 0x74, 0x4d, 0xdc,
0x88, 0x4c, 0xef, 0x9c, 0x23, 0xb8, 0x15, 0x4b, 0x41, 0x49, 0xd8, 0x4b, 0xf3, 0xca, 0x6b, 0xb3,
0xa7, 0x93, 0x66, 0xe9, 0xbe, 0x77, 0x46, 0xe7, 0xc4, 0xe9, 0x6a, 0x2a, 0x89, 0x1b, 0x97, 0x13,
0x8f, 0x51, 0x86, 0xe8, 0x35, 0xd8, 0x6a, 0xae, 0xf3, 0x5e, 0x44, 0xe2, 0xd8, 0x3f, 0xa3, 0x3d,
0x37, 0x2d, 0xc8, 0x5e, 0xaa, 0x5a, 0xf5, 0x02, 0xbe, 0xab, 0xc7, 0x3b, 0xc9, 0xf0, 0xb8, 0xbe,
0xda, 0xef, 0x0c, 0xd8, 0xed, 0x81, 0xfc, 0x8f, 0xad, 0x1e, 0xc0, 0x72, 0x4c, 0x59, 0xbf, 0x27,
0x4f, 0x05, 0x1f, 0x78, 0xa7, 0xa6, 0xd7, 0x1b, 0xf4, 0x52, 0x52, 0xd8, 0x51, 0x42, 0xcd, 0xca,
0x2d, 0xfb, 0xef, 0xb9, 0x7d, 0x83, 0x72, 0x24, 0xf8, 0xc5, 0x70, 0x6c, 0x9a, 0x34, 0xbb, 0x73,
0x8d, 0x69, 0x47, 0x41, 0xc6, 0x73, 0x45, 0x3b, 0xa4, 0x96, 0x53, 0x7b, 0xa8, 0xf6, 0x33, 0x03,
0x79, 0x13, 0xe8, 0x3b, 0x58, 0xf2, 0x93, 0x13, 0x64, 0x5b, 0xd5, 0x6c, 0xbd, 0x74, 0xf9, 0xea,
0x98, 0x73, 0xb8, 0xf0, 0x88, 0x41, 0x1f, 0xa0, 0xc0, 0x4d, 0x57, 0x76, 0x46, 0xf3, 0x1b, 0x93,
0xfc, 0xbc, 0x1e, 0x71, 0x4a, 0xa1, 0x06, 0x64, 0x03, 0xee, 0x99, 0xe8, 0xd6, 0x66, 0x96, 0xe9,
0x39, 0x86, 0x52, 0x4a, 0xf4, 0x06, 0xb2, 0x24, 0x8a, 0xec, 0x9c, 0x9e, 0xed, 0xc6, 0xed, 0x2b,
0x06, 0xbd, 0x85, 0x62, 0x1a, 0x9d, 0xc9, 0xf5, 0xe1, 0xec, 0x5c, 0xcd, 0x84, 0x63, 0xf9, 0xce,
0x16, 0x2c, 0x27, 0x2f, 0x3f, 0x71, 0x11, 0x12, 0xa9, 0x6e, 0xa2, 0x8e, 0xba, 0xfa, 0x8f, 0x07,
0x27, 0x95, 0x05, 0x54, 0x80, 0xdc, 0xe7, 0x6e, 0xfb, 0x6b, 0xc5, 0xda, 0x5f, 0x87, 0xb2, 0xcb,
0xc3, 0x09, 0xd7, 0xfd, 0x52, 0xc2, 0x69, 0xf5, 0xf7, 0x9c, 0x7a, 0x75, 0x9c, 0xd7, 0xff, 0x1a,
0x2f, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0xe4, 0x6f, 0x70, 0x9e, 0x57, 0x07, 0x00, 0x00,
}

95
config.proto Normal file
View File

@@ -0,0 +1,95 @@
syntax = "proto3";
package v2ray.core;
option go_package = "core";
option java_package = "com.v2ray.core";
option java_outer_classname = "ConfigProto";
import "v2ray.com/core/common/loader/type.proto";
import "v2ray.com/core/common/net/port.proto";
import "v2ray.com/core/common/net/address.proto";
import "v2ray.com/core/common/log/config.proto";
import "v2ray.com/core/transport/internet/config.proto";
import "v2ray.com/core/transport/config.proto";
// Configuration serialization format.
enum ConfigFormat {
Protobuf = 0;
JSON = 1;
}
message AllocationStrategyConcurrency {
uint32 value = 1;
}
message AllocationStrategyRefresh {
uint32 value = 1;
}
message AllocationStrategy {
enum Type {
// Always allocate all connection handlers.
Always = 0;
// Randomly allocate specific range of handlers.
Random = 1;
// External. Not supported yet.
External = 2;
}
Type type = 1;
// Number of handlers (ports) running in parallel.
// Default value is 3 if unset.
AllocationStrategyConcurrency concurrency = 2;
// Number of minutes before a handler is regenerated.
// Default value is 5 if unset.
AllocationStrategyRefresh refresh = 3;
}
// Config for an inbound connection handler.
message InboundConnectionConfig {
// Protocol specific settings. Must be one of the supported protocols.
v2ray.core.common.loader.TypedSettings settings = 1;
// Range of port number to run on. Both inclusive.
v2ray.core.common.net.PortRange port_range = 2;
// IP address to listen on. 0.0.0.0 if unset.
v2ray.core.common.net.IPOrDomain listen_on = 3;
// Tag of this handler.
string tag = 4;
AllocationStrategy allocation_strategy = 5;
v2ray.core.transport.internet.StreamConfig stream_settings = 6;
bool allow_passive_connection = 7;
}
// Config for an outbound connection handler.
message OutboundConnectionConfig {
v2ray.core.common.loader.TypedSettings settings = 1;
// IP address to send data through. 0.0.0.0 if unset.
v2ray.core.common.net.IPOrDomain send_through = 2;
v2ray.core.transport.internet.StreamConfig stream_settings = 3;
v2ray.core.transport.internet.ProxyConfig proxy_settings = 5;
string tag = 4;
}
message Config {
// Inbound handler configurations. Must have at least one item.
repeated InboundConnectionConfig inbound = 1;
// Outbound handler configurations. Must have at least one item. The first item is used as default for routing.
repeated OutboundConnectionConfig outbound = 2;
v2ray.core.common.log.Config log = 3;
// App configuration. Must be one in the app directory.
repeated v2ray.core.common.loader.TypedSettings app = 4;
v2ray.core.transport.Config transport = 5;
}

40
config_loader.go Normal file
View File

@@ -0,0 +1,40 @@
package core
import (
"io"
"io/ioutil"
"v2ray.com/core/common"
"github.com/golang/protobuf/proto"
)
type ConfigLoader func(input io.Reader) (*Config, error)
var configLoaderCache = make(map[ConfigFormat]ConfigLoader)
func RegisterConfigLoader(format ConfigFormat, loader ConfigLoader) error {
configLoaderCache[format] = loader
return nil
}
func LoadConfig(format ConfigFormat, input io.Reader) (*Config, error) {
loader, found := configLoaderCache[format]
if !found {
return nil, common.ErrBadConfiguration
}
return loader(input)
}
func LoadProtobufConfig(input io.Reader) (*Config, error) {
config := new(Config)
data, _ := ioutil.ReadAll(input)
if err := proto.Unmarshal(data, config); err != nil {
return nil, err
}
return config, nil
}
func init() {
RegisterConfigLoader(ConfigFormat_Protobuf, LoadProtobufConfig)
}

View File

@@ -8,7 +8,7 @@ import (
)
var (
version = "2.3"
version = "2.8"
build = "Custom"
codename = "One for all"
intro = "An unified platform for anti-censorship."

View File

@@ -1,4 +1,4 @@
package point
package core
import (
"v2ray.com/core/proxy"

View File

@@ -1,4 +1,4 @@
package point
package core
import (
"v2ray.com/core/app"
@@ -12,11 +12,11 @@ import (
// Handler for inbound detour connections.
type InboundDetourHandlerAlways struct {
space app.Space
config *InboundDetourConfig
config *InboundConnectionConfig
ich []proxy.InboundHandler
}
func NewInboundDetourHandlerAlways(space app.Space, config *InboundDetourConfig) (*InboundDetourHandlerAlways, error) {
func NewInboundDetourHandlerAlways(space app.Space, config *InboundConnectionConfig) (*InboundDetourHandlerAlways, error) {
handler := &InboundDetourHandlerAlways{
space: space,
config: config,
@@ -24,9 +24,12 @@ func NewInboundDetourHandlerAlways(space app.Space, config *InboundDetourConfig)
ports := config.PortRange
handler.ich = make([]proxy.InboundHandler, 0, ports.To-ports.From+1)
for i := ports.FromPort(); i <= ports.ToPort(); i++ {
ichConfig := config.Settings
ich, err := proxyregistry.CreateInboundHandler(config.Protocol, space, ichConfig, &proxy.InboundHandlerMeta{
Address: config.ListenOn,
ichConfig, err := config.GetTypedSettings()
if err != nil {
return nil, err
}
ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, space, ichConfig, &proxy.InboundHandlerMeta{
Address: config.GetListenOnValue(),
Port: i,
Tag: config.Tag,
StreamSettings: config.StreamSettings,
@@ -43,7 +46,7 @@ func NewInboundDetourHandlerAlways(space app.Space, config *InboundDetourConfig)
func (this *InboundDetourHandlerAlways) GetConnectionHandler() (proxy.InboundHandler, int) {
ich := this.ich[dice.Roll(len(this.ich))]
return ich, this.config.Allocation.Refresh
return ich, int(this.config.GetAllocationStrategyValue().Refresh.GetValue())
}
func (this *InboundDetourHandlerAlways) Close() {
@@ -55,7 +58,7 @@ func (this *InboundDetourHandlerAlways) Close() {
// Starts the inbound connection handler.
func (this *InboundDetourHandlerAlways) Start() error {
for _, ich := range this.ich {
err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error {
err := retry.ExponentialBackoff(10 /* times */, 200 /* ms */).On(func() error {
err := ich.Start()
if err != nil {
log.Error("Failed to start inbound detour:", err)

View File

@@ -1,4 +1,4 @@
package point
package core
import (
"sync"
@@ -16,24 +16,28 @@ import (
type InboundDetourHandlerDynamic struct {
sync.RWMutex
space app.Space
config *InboundDetourConfig
config *InboundConnectionConfig
portsInUse map[v2net.Port]bool
ichs []proxy.InboundHandler
ich2Recyle []proxy.InboundHandler
lastRefresh time.Time
}
func NewInboundDetourHandlerDynamic(space app.Space, config *InboundDetourConfig) (*InboundDetourHandlerDynamic, error) {
func NewInboundDetourHandlerDynamic(space app.Space, config *InboundConnectionConfig) (*InboundDetourHandlerDynamic, error) {
handler := &InboundDetourHandlerDynamic{
space: space,
config: config,
portsInUse: make(map[v2net.Port]bool),
}
handler.ichs = make([]proxy.InboundHandler, config.Allocation.Concurrency)
handler.ichs = make([]proxy.InboundHandler, config.GetAllocationStrategyValue().Concurrency.GetValue())
// To test configuration
ich, err := proxyregistry.CreateInboundHandler(config.Protocol, space, config.Settings, &proxy.InboundHandlerMeta{
Address: config.ListenOn,
ichConfig, err := config.GetTypedSettings()
if err != nil {
return nil, err
}
ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, space, ichConfig, &proxy.InboundHandlerMeta{
Address: config.GetListenOnValue(),
Port: 0,
Tag: config.Tag,
StreamSettings: config.StreamSettings,
@@ -64,7 +68,7 @@ func (this *InboundDetourHandlerDynamic) GetConnectionHandler() (proxy.InboundHa
this.RLock()
defer this.RUnlock()
ich := this.ichs[dice.Roll(len(this.ichs))]
until := this.config.Allocation.Refresh - int((time.Now().Unix()-this.lastRefresh.Unix())/60/1000)
until := int(this.config.GetAllocationStrategyValue().Refresh.GetValue()) - int((time.Now().Unix()-this.lastRefresh.Unix())/60/1000)
if until < 0 {
until = 0
}
@@ -98,13 +102,14 @@ func (this *InboundDetourHandlerDynamic) refresh() error {
config := this.config
this.ich2Recyle = this.ichs
newIchs := make([]proxy.InboundHandler, config.Allocation.Concurrency)
newIchs := make([]proxy.InboundHandler, config.GetAllocationStrategyValue().Concurrency.GetValue())
for idx := range newIchs {
err := retry.Timed(5, 100).On(func() error {
port := this.pickUnusedPort()
ich, err := proxyregistry.CreateInboundHandler(config.Protocol, this.space, config.Settings, &proxy.InboundHandlerMeta{
Address: config.ListenOn, Port: port, Tag: config.Tag, StreamSettings: config.StreamSettings})
ichConfig, _ := config.GetTypedSettings()
ich, err := proxyregistry.CreateInboundHandler(config.Settings.Type, this.space, ichConfig, &proxy.InboundHandlerMeta{
Address: config.GetListenOnValue(), Port: port, Tag: config.Tag, StreamSettings: config.StreamSettings})
if err != nil {
delete(this.portsInUse, port)
return err
@@ -140,7 +145,7 @@ func (this *InboundDetourHandlerDynamic) Start() error {
go func() {
for {
time.Sleep(time.Duration(this.config.Allocation.Refresh)*time.Minute - 1)
time.Sleep(time.Duration(this.config.GetAllocationStrategyValue().Refresh.GetValue())*time.Minute - 1)
this.RecyleHandles()
err := this.refresh()
if err != nil {

Some files were not shown because too many files have changed in this diff Show More