Compare commits

..

361 Commits

Author SHA1 Message Date
v2ray
443e9d4725 fix a bug in vmess encoding 2016-07-27 16:36:46 +02:00
Darien Raymond
c5e5a7265d Update to go 1.6.3 2016-07-27 13:30:57 +02:00
v2ray
6fe7463bf4 simplify state checking 2016-07-26 21:34:00 +02:00
v2ray
0040881b84 comments 2016-07-26 21:21:22 +02:00
v2ray
347ae8fd75 simplify interface 2016-07-26 17:25:13 +02:00
v2ray
ca0ae50e62 refine system dialer substitution 2016-07-26 17:11:58 +02:00
Darien Raymond
27a29da7bf Merge pull request #219 from xiaokangwang/substituteDialer
Solve #218: Supporting substitute of the default Dialer.
2016-07-26 16:33:14 +02:00
Shelikhoo
d1b44619b0 Solve #218: Supporting substitute of the default Dialer, this is a prerequisite of Libv2ray's support of Android VPNService mode; It is not recommanded to modify exported func introduced by this commit. 2016-07-26 16:33:12 +08:00
v2ray
b72afc7c35 fix build break 2016-07-26 10:23:02 +02:00
v2ray
6a620d1c6d socks client config 2016-07-25 23:45:25 +02:00
v2ray
a509252c24 prefer pointer 2016-07-25 21:55:05 +02:00
v2ray
a29a6a586d one more test case 2016-07-25 21:43:57 +02:00
v2ray
c96533f278 test case for server picker 2016-07-25 21:43:31 +02:00
v2ray
f4aa50a160 test code for validation strategy 2016-07-25 21:31:16 +02:00
v2ray
2034d54bab rename VMessAccount to vmess.Account 2016-07-25 17:36:24 +02:00
v2ray
2049759640 use server spec in vmess 2016-07-25 16:48:09 +02:00
v2ray
b02bd5b1d8 rollback chacha20 change 2016-07-25 10:28:11 +02:00
v2ray
7dfa852677 server spec 2016-07-24 23:22:46 +02:00
v2ray
03af6e6856 update version 2016-07-24 16:04:30 +02:00
v2ray
dbee8c620a update china ip 2016-07-24 13:44:49 +02:00
v2ray
ea39a6fde6 format code 2016-07-24 13:44:29 +02:00
v2ray
0857fdb0f8 test code for blackhole config 2016-07-24 13:40:27 +02:00
v2ray
f871ca63e2 refine error message 2016-07-24 11:29:59 +02:00
v2ray
723a693c78 delete port after error 2016-07-24 10:08:06 +02:00
v2ray
edd9885d0e retry on port allocation 2016-07-24 10:06:50 +02:00
v2ray
96ec5cfc58 Fix VMess inbound for empty response 2016-07-24 09:59:52 +02:00
v2ray
6f5b54747e move encoding to vmess 2016-07-23 13:17:51 +02:00
v2ray
e304e2761d refine chacha20 initialization 2016-07-23 13:04:44 +02:00
v2ray
128e866021 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2016-07-23 12:53:18 +02:00
Darien Raymond
08526a32ff Merge pull request #215 from aead/master
Replace ChaCha20 implementation with an optimized version
2016-07-23 12:53:07 +02:00
v2ray
3be5045dfc replace NewSmallBuffer with NewLocalBuffer 2016-07-23 11:55:57 +02:00
v2ray
84a7a2ad61 correct initialization in socks server 2016-07-23 11:09:49 +02:00
Andreas Auernhammer
0cd0033245 Replace ChaCha20 implementation with an optimized version 2016-07-23 08:48:48 +02:00
v2ray
85d6e1ad13 prepend hash 2016-07-17 23:11:05 +02:00
v2ray
1931820c4c leverage local buffer 2016-07-17 12:59:57 +02:00
v2ray
7e499ee0b6 Cleanup 2016-07-17 12:18:34 +02:00
v2ray
089de290ad Leverage buffer.Read 2016-07-17 12:18:26 +02:00
v2ray
a39132f4c2 update log 2016-07-16 22:14:20 +02:00
v2ray
bf2d45a83d use local buffer when fetching input 2016-07-16 22:08:59 +02:00
Darien Raymond
00a747afe3 Update ISSUE_TEMPLATE 2016-07-16 18:31:26 +02:00
Darien Raymond
f072d26fe4 Rename ISSUE_TEMPLATE.md to ISSUE_TEMPLATE 2016-07-16 18:30:07 +02:00
Darien Raymond
187a89484c Rename ISSUE_TEMPLATE to ISSUE_TEMPLATE.md 2016-07-16 18:27:53 +02:00
Darien Raymond
b2cd65d6bc Update ISSUE_TEMPLATE 2016-07-16 18:27:09 +02:00
Darien Raymond
acb01e6177 Update ISSUE_TEMPLATE 2016-07-16 18:25:52 +02:00
Darien Raymond
45423add40 Create ISSUE_TEMPLATE 2016-07-16 18:21:52 +02:00
v2ray
3f396078ab remove unnecessary buffer 2016-07-16 13:22:34 +02:00
v2ray
4aadaa7513 use local stack buffer 2016-07-16 13:22:18 +02:00
v2ray
f45fa6e918 allow buffer on local stack 2016-07-16 13:22:08 +02:00
v2ray
8d3da0ed8e remove unnecessary use of buffer 2016-07-16 12:11:45 +02:00
v2ray
e586f3c127 release buffer on write error 2016-07-16 11:12:53 +02:00
v2ray
17ea740e7e remove unnecessary use of buffer 2016-07-16 10:45:32 +02:00
v2ray
066e5e216d fill windows after processing acks 2016-07-15 23:23:21 +02:00
v2ray
72ee6436eb more accurate of rtt calculation 2016-07-15 23:18:18 +02:00
v2ray
d5cd919cec remove duplicated code 2016-07-15 21:41:15 +02:00
v2ray
f6d4e599bd configurable read and write buffer size 2016-07-15 21:27:23 +02:00
v2ray
b6a6c154a3 remove unnecessary use of buffer 2016-07-15 21:15:41 +02:00
v2ray
33e0cfe233 fully allocate buffer pools 2016-07-15 15:17:06 +02:00
v2ray
9e8ed30052 update buffer pool size 2016-07-15 15:16:35 +02:00
v2ray
9523cb3ec3 refine buffer struct 2016-07-15 14:24:20 +02:00
v2ray
631db6e69a rename 2016-07-14 22:52:00 +02:00
v2ray
ef2d49302d rename command 2016-07-14 22:10:37 +02:00
v2ray
ffdce592ec remove sync.Pool from segment allocation 2016-07-14 21:42:00 +02:00
v2ray
906d846c2e update test case 2016-07-14 21:31:54 +02:00
v2ray
c32f1a0152 update test case 2016-07-14 21:31:04 +02:00
v2ray
991b2703dc improve writing performance 2016-07-14 17:39:12 +02:00
v2ray
0acd3b6d62 improve sending performance 2016-07-14 17:38:20 +02:00
v2ray
6f998fa18b update ipv6 comparison 2016-07-14 14:25:06 +02:00
v2ray
476b3c68d2 introduce a new state: peer terminating 2016-07-14 12:57:14 +02:00
v2ray
05ed05b9a0 correctly release segments 2016-07-13 23:15:40 +02:00
v2ray
73afe9a001 use alloc.Buffer in sending queue 2016-07-13 21:47:40 +02:00
v2ray
c7b0264f9a lock in udp hub 2016-07-13 21:39:18 +02:00
v2ray
fc69c77369 fix an offset issue in OTA 2016-07-13 11:38:14 +02:00
v2ray
d602025908 update test performance 2016-07-13 09:19:51 +02:00
v2ray
c0a1198514 improve terminating performance 2016-07-12 23:54:54 +02:00
v2ray
9a44ff3145 static conv 2016-07-12 18:54:16 +02:00
v2ray
9434f5156c fix memory leak 2016-07-12 18:27:14 +02:00
v2ray
b9bf419f57 update version 2016-07-12 18:02:26 +02:00
v2ray
205f8b382d Fix race condition 2016-07-12 17:56:36 +02:00
v2ray
94d4b02191 non blocking flusing 2016-07-12 17:37:12 +02:00
v2ray
b68075a99d test case for kcp read write 2016-07-12 17:11:36 +02:00
v2ray
4c63e9e168 improve fetch performance 2016-07-12 14:32:17 +02:00
v2ray
f7d54d57c4 remove lastpayloadtime 2016-07-12 14:23:42 +02:00
v2ray
b50671f041 fix a bug in process ack 2016-07-12 13:43:25 +02:00
v2ray
63390786ed test case for read timeout 2016-07-12 13:27:12 +02:00
v2ray
a88a120938 Fix deadlock in kcp.read 2016-07-12 12:54:09 +02:00
v2ray
e13ea7a54f refine log in vmess 2016-07-12 00:12:35 +02:00
v2ray
12d13f1560 refine log in KCP 2016-07-11 17:24:35 +02:00
v2ray
f5fd76ab85 var -> const 2016-07-11 15:54:19 +02:00
v2ray
566adec285 allow customized timeout in socks protocol 2016-07-11 15:46:18 +02:00
v2ray
96c6012013 refine main thread to capture all logs 2016-07-10 23:11:42 +02:00
v2ray
636effbe38 more accurate source id 2016-07-10 15:58:55 +02:00
v2ray
30041041d3 timeout settings in http proxy 2016-07-10 15:34:14 +02:00
v2ray
5e7d413404 allow insecure connections 2016-07-10 15:30:48 +02:00
v2ray
be81d246f2 rename json fields 2016-07-10 15:29:03 +02:00
v2ray
754e8b6e78 tls config 2016-07-10 15:27:58 +02:00
v2ray
1e3ebeef59 reduce buffer size 2016-07-06 17:58:15 +02:00
v2ray
56ce062154 refine connection.read 2016-07-06 17:34:38 +02:00
v2ray
a615afc906 refine locks in sending worker 2016-07-06 16:36:15 +02:00
v2ray
5448ec1fe4 refine locker in sending worker 2016-07-06 00:02:22 +02:00
v2ray
78ef65e17b refine locker in kcp connection 2016-07-05 23:53:46 +02:00
v2ray
e44b374e66 merge kcp into connection 2016-07-05 23:02:52 +02:00
v2ray
344e48e1bb completely remove itimediff 2016-07-05 21:47:35 +02:00
v2ray
16d1b42f59 refine seg allocation 2016-07-05 14:08:08 +02:00
v2ray
6efff7654c leverage pool functions 2016-07-05 11:36:05 +02:00
v2ray
34fb72e7c6 refine ack seg put 2016-07-05 10:33:11 +02:00
v2ray
13e83c17a5 apply sync.Pool to segments 2016-07-05 10:28:23 +02:00
v2ray
e170750d7e fix test 2016-07-04 17:01:32 +02:00
v2ray
6ea8691a07 correctly apply cwnd 2016-07-04 15:54:18 +02:00
v2ray
d1d153acb9 refine congestion control 2016-07-04 15:34:14 +02:00
v2ray
8ea3c13236 rename ISegment -> Segment 2016-07-04 14:17:42 +02:00
v2ray
03ff683686 rename process ack segment 2016-07-04 14:17:11 +02:00
v2ray
165e323fab refine sending window size 2016-07-04 13:37:42 +02:00
v2ray
6a1054a0f3 allow capacity = 0 2016-07-04 13:31:21 +02:00
v2ray
d5cb2e88c9 Fix Shadowsocks OTA 2016-07-04 09:47:14 +02:00
v2ray
9c3ebc0453 allow control window larger than sending window 2016-07-03 23:16:48 +02:00
v2ray
968fffcffb fix test break 2016-07-03 22:33:08 +02:00
v2ray
2c259165ff read entire small payload 2016-07-03 22:32:28 +02:00
v2ray
e4acfe7f7e sending worker 2016-07-03 22:14:38 +02:00
v2ray
54b791821e remove unnecessary log 2016-07-03 09:40:22 +02:00
v2ray
0eaa3ba27a refactor code 2016-07-03 09:38:51 +02:00
v2ray
f8a614714c sending window fix 2016-07-03 09:38:40 +02:00
v2ray
ab2cef1c09 shrink_buf 2016-07-03 00:57:28 +02:00
v2ray
84889117e9 simplify logic 2016-07-03 00:38:33 +02:00
v2ray
e5c4fd3e1c remove unused variables 2016-07-03 00:27:01 +02:00
v2ray
490f77b4a0 cleanup 2016-07-03 00:00:43 +02:00
v2ray
7bc6d8af88 remove nodelay function 2016-07-02 23:59:43 +02:00
v2ray
951b278ac7 test case for receiving queue 2016-07-02 23:37:51 +02:00
v2ray
6416c42bee rename NewAckList 2016-07-02 23:18:12 +02:00
v2ray
a1af9ea839 refine locks 2016-07-02 22:28:28 +02:00
v2ray
3ad83da7cb rename acksegment 2016-07-02 22:17:41 +02:00
v2ray
32da784549 remove deadlock 2016-07-02 22:06:37 +02:00
v2ray
080f0abee9 receiving worker 2016-07-02 21:26:50 +02:00
v2ray
3e84e4cb44 rename acklist 2016-07-02 11:33:34 +02:00
v2ray
e1ce179b8e remove unnecessary constants 2016-07-02 11:31:15 +02:00
v2ray
94fb16fdfa refine kcp constructor 2016-07-02 11:19:32 +02:00
v2ray
a2abdc3d2f refine mtu settings 2016-07-02 08:45:31 +02:00
v2ray
8e98ede75d shrink buf in time 2016-07-01 23:27:57 +02:00
v2ray
2169dcd7da fix a bug in length calculation 2016-07-01 22:54:59 +02:00
v2ray
6ca4eaf3b6 update default capacity in config files 2016-07-01 17:51:50 +02:00
v2ray
829355e6bf correctly calculate len of sending window 2016-07-01 15:54:04 +02:00
Darien Raymond
5714ae3935 Update README.md 2016-07-01 12:49:40 +02:00
Darien Raymond
c61db151df Update README.md 2016-07-01 12:43:35 +02:00
v2ray
dc53575540 bug fixes in sending window 2016-07-01 12:12:32 +02:00
v2ray
4c74e25319 sending window 2016-07-01 11:57:13 +02:00
v2ray
48d4f5b7bb remove acklist test for the moment 2016-07-01 11:57:06 +02:00
v2ray
aa46e4ea05 extend ack timeout 2016-06-30 22:19:57 +02:00
v2ray
d63330d15e refine ack list flushing 2016-06-30 22:19:30 +02:00
v2ray
5680c69146 locker protected ReceivingQueue.Put 2016-06-30 16:58:38 +02:00
v2ray
a1f5839461 receiving queue 2016-06-30 14:51:49 +02:00
v2ray
a6649fa0ff remove unused variables 2016-06-30 11:35:35 +02:00
v2ray
9d83fbcb7c fix cwnd 2016-06-30 11:19:35 +02:00
v2ray
7aa848dc02 remove unused import 2016-06-30 10:47:33 +02:00
v2ray
7056b414e2 length protection in ReadSegment 2016-06-30 00:12:36 +02:00
v2ray
f050113925 fix #185 2016-06-30 00:08:20 +02:00
v2ray
98cc28a4c4 leverage dice.Roll 2016-06-29 23:53:50 +02:00
v2ray
71c9bd678c Fix receiving update 2016-06-29 23:41:04 +02:00
v2ray
313b3c1db0 shrink buf for all type of segments 2016-06-29 22:49:38 +02:00
v2ray
812ac54290 congestion control 2016-06-29 22:30:38 +02:00
v2ray
af5a2ac0bc allow small capacity 2016-06-29 16:46:26 +02:00
v2ray
6e615c5863 correctly measure payload time 2016-06-29 14:49:49 +02:00
v2ray
c5170a36f0 agreesively close unresponding connections 2016-06-29 13:42:11 +02:00
v2ray
0047910a81 bug fixes 2016-06-29 12:52:23 +02:00
v2ray
d958b9884e apply new classes to kcp core 2016-06-29 10:34:34 +02:00
v2ray
aa6726a6d0 segment.releasable 2016-06-27 22:54:59 +02:00
v2ray
41b230994e segment writer 2016-06-27 22:52:48 +02:00
v2ray
beea2528ce ack list 2016-06-27 22:34:46 +02:00
v2ray
6915095a0a typed segments 2016-06-27 22:22:01 +02:00
v2ray
27b8715b63 refine rto settings 2016-06-27 17:05:01 +02:00
Darien Raymond
52c6b9b60b Update README.md 2016-06-27 12:33:38 +02:00
v2ray
32d9984e28 completely remove wnd probe 2016-06-27 12:16:36 +02:00
v2ray
5a5c9b891d correct window calculation 2016-06-27 11:18:14 +02:00
v2ray
2e63b29191 correct srtt boundary 2016-06-27 09:14:30 +02:00
v2ray
231f5fc140 update RecivingWindow.Remove 2016-06-27 09:03:05 +02:00
v2ray
7f661f5215 rename Error to Err 2016-06-27 08:53:35 +02:00
v2ray
5ee87404fd remove unused variable 2016-06-27 08:47:47 +02:00
v2ray
e9fdc35c3c fix kcp dial log 2016-06-27 08:38:02 +02:00
v2ray
cf6d36ecd5 remove unnecessary flush 2016-06-27 00:04:28 +02:00
v2ray
3925b62751 high performance sending queue 2016-06-26 23:51:17 +02:00
v2ray
67ac925ee7 refactor bytes functions 2016-06-26 22:34:48 +02:00
v2ray
d12d5b0593 fix data structure 2016-06-25 23:28:22 +02:00
v2ray
d37c01905c remove unnecessary conversion 2016-06-25 23:18:05 +02:00
v2ray
0812d7f9be change writeBuffer to uint32 2016-06-25 23:17:04 +02:00
v2ray
5b70c33c77 remove tti check 2016-06-25 23:08:02 +02:00
v2ray
882746380e Correct RTT Variation 2016-06-25 22:10:17 +02:00
v2ray
25ef62434a high performance receiving window 2016-06-25 21:35:18 +02:00
v2ray
87e1d66ff0 remove segment.rto 2016-06-25 17:34:07 +02:00
v2ray
15f190d268 remove nodelay settings 2016-06-25 17:32:09 +02:00
Darien Raymond
6257dfa247 Remove Gitter badge 2016-06-24 23:15:33 +02:00
v2ray
0613d0cf22 Clear sending queue when peer closed 2016-06-23 23:17:17 +02:00
v2ray
ab710f2714 write buffer size 2016-06-23 22:37:48 +02:00
v2ray
4beeba933c refine rto and wnd, temporarily disable congestion control 2016-06-23 22:37:38 +02:00
v2ray
576b16c2f7 remove unused variable 2016-06-23 16:06:18 +02:00
v2ray
db3ca752ff remove unused methods 2016-06-22 21:03:15 +02:00
v2ray
0327113fb8 lock protected user validator 2016-06-22 15:21:40 +02:00
v2ray
6847139ae3 renamed ErrObjectReleased 2016-06-22 15:12:57 +02:00
V2Ray Dev
3729ad2330 Update default capacity 2016-06-20 23:24:10 +02:00
V2Ray Dev
41225f8c12 correctly set tti 2016-06-20 22:27:25 +02:00
v2ray
6ec9032a54 update default config 2016-06-20 16:24:59 +02:00
v2ray
1238304b1d more settings to kcp 2016-06-20 16:10:47 +02:00
V2Ray Dev
b131f64f7b remove acknodealy setting entry 2016-06-20 11:06:27 +02:00
V2Ray Dev
1cd5372a5a 'comment'
Signed-off-by: V2Ray Dev <admin@v2ray.com>
2016-06-19 17:02:20 +02:00
V2Ray Dev
143829e065 'comment'
Signed-off-by: V2Ray Dev <admin@v2ray.com>
2016-06-19 16:55:50 +02:00
v2ray
299f866997 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2016-06-19 16:06:45 +02:00
v2ray
5fb9f10fc2 Update log
Can't stop dreaming of you
2016-06-19 16:06:40 +02:00
v2ray
fb41233051 Update version 2016-06-19 16:05:40 +02:00
v2ray
560b429902 Update log 2016-06-19 02:02:38 +02:00
v2ray
aa38488712 clean up sessions 2016-06-18 21:18:21 +02:00
v2ray
8cd32a8267 avoid copying segment structure 2016-06-18 19:08:02 +02:00
v2ray
ee0c25b0f3 reuse alloc.buffer in kcp 2016-06-18 18:53:29 +02:00
v2ray
7bf74761df remove unused code in kcp 2016-06-18 17:30:31 +02:00
v2ray
a0d08e4961 check mtu setting 2016-06-18 17:14:39 +02:00
v2ray
16f5f81fe9 enlarge small buffer to fix common mtu size 2016-06-18 17:14:30 +02:00
v2ray
20f046af0b fix a race condition issue in VMess inbound 2016-06-18 17:01:48 +02:00
v2ray
bac9304e05 better termination logic 2016-06-18 16:52:02 +02:00
v2ray
5334d25e16 normalize naming 2016-06-18 16:34:04 +02:00
v2ray
cd4416e7e5 another test case for simple authenticator 2016-06-18 10:58:21 +02:00
v2ray
b5ab714b52 fix duplicated asm function 2016-06-18 10:47:15 +02:00
v2ray
f54da94d03 update asm code 2016-06-18 02:19:18 +02:00
v2ray
f7396aad8c improve simple authenticator performance in amd64 2016-06-18 02:13:35 +02:00
v2ray
2b966b039f check for nil 2016-06-17 23:50:08 +02:00
v2ray
7a84c930d4 fix KCP 2016-06-17 23:09:26 +02:00
v2ray
87cb0d5dc9 update log 2016-06-17 18:03:31 +02:00
v2ray
233b73d1db improve kcp performance 2016-06-17 17:38:42 +02:00
v2ray
f5d613f10a update kcp config 2016-06-17 16:57:48 +02:00
v2ray
42ae2d804f Integrate kcp with other components 2016-06-17 16:51:41 +02:00
v2ray
e5394cdaa0 Check if inbound and outbound config are set. 2016-06-15 11:58:28 +02:00
v2ray
103c721626 adjust connection type priority 2016-06-15 01:08:03 +02:00
v2ray
9d21c78a01 remove ibound function 2016-06-15 01:06:02 +02:00
v2ray
b8160bbdae merge dial and listen functions 2016-06-15 00:30:11 +02:00
v2ray
c4536d99d4 test case for raw connection 2016-06-15 00:10:52 +02:00
v2ray
99516bc511 customizable kcp code 2016-06-14 23:25:06 +02:00
v2ray
71ce8f4416 enable kcp 2016-06-14 23:00:00 +02:00
v2ray
9b6dc6bcea massive refactoring for kcp 2016-06-14 22:54:08 +02:00
Darien Raymond
22ce652a25 Merge pull request #170 from xiaokangwang/kcptransport
Add KCP(UDPSession) as a transport for v2ray, reslove #162
2016-06-13 16:35:57 +02:00
Shelikhoo
de4b4516ee Fix: check jsonConfig.KcpConfig 2016-06-13 17:49:21 +08:00
Shelikhoo
bcf87d1592 KCP: style 2016-06-13 16:34:35 +08:00
Shelikhoo
14623e6fa4 KCP: This code cause unwanted effect 2016-06-13 16:01:27 +08:00
Shelikhoo
18841209ee KCP:Some Tests 2016-06-13 15:57:49 +08:00
v2ray
c8da174a7a update install-release.sh 2016-06-13 09:25:19 +02:00
Shelikhoo
0f368f8139 KCP: comments 2016-06-13 15:03:58 +08:00
Shelikhoo
29e9473026 KCP: delay conn close to prevent conn leak+ 2016-06-13 12:56:37 +08:00
Shelikhoo
9144b66217 KCP: delay conn close to prevent conn leak 2016-06-13 07:08:40 +08:00
Shelikhoo
4df5d42011 KCP: discard useless conn in Accept+ 2016-06-13 06:17:28 +08:00
Shelikhoo
f601962391 KCP: discard useless conn in Accept 2016-06-13 06:16:44 +08:00
v2ray
8a5f37dad7 check if address is set 2016-06-12 22:54:33 +02:00
Shelikhoo
f4ff2e9366 Removed manadory mandatory requirement for Read/Write Timeout+ 2016-06-12 22:39:38 +08:00
Shelikhoo
d0d63ee5b3 Removed manadory mandatory requirement for Read/Write Timeout 2016-06-12 22:37:50 +08:00
Shelikhoo
9315bb29fb Fix: Dial3 misbehave 2016-06-12 15:21:59 +08:00
Shelikhoo
579786166c Fix: DialWithoutCache3 misbehave 2016-06-12 15:15:47 +08:00
Shelikhoo
7fdf0de06d KCP: Fixed: typo in <Fixed transport/config_json.go jsonConfig.KcpConfig, jsonConfig.KcpConfig.AdvancedConfig == nil> 2016-06-12 14:12:48 +08:00
Shelikhoo
cbb183ec58 KCP: Fixed transport/config_json.go jsonConfig.KcpConfig, jsonConfig.KcpConfig.AdvancedConfig == nil 2016-06-12 14:10:19 +08:00
Shelikhoo
e72a7cb96f KCP: VMess will call setProxyCap to advertise KCP capacity on init 2016-06-12 13:57:08 +08:00
Shelikhoo
29cb680a4b KCP: VMess will advertise its KCP capacity 2016-06-12 13:52:29 +08:00
Shelikhoo
6d6158b089 KCP: Vmess will pass its meta to Dial3 and ListenTCP6 2016-06-12 13:48:40 +08:00
Shelikhoo
0912574166 KCP: amend proxyMeta -> *proxymeta 2016-06-12 13:45:21 +08:00
Shelikhoo
4f9a9d1f0c KCP: fix: meta type 2016-06-12 13:43:05 +08:00
Shelikhoo
c07d478ab5 KCP: Dialers for KCP 2016-06-12 13:38:14 +08:00
Shelikhoo
35b30e5bb0 Finished ListenKCPhub 2016-06-12 13:22:09 +08:00
Shelikhoo
70201d8879 KCP:func ListenKCP finished 2016-06-12 13:14:07 +08:00
Shelikhoo
a9ef8d27bd Merged latest master 2016-06-12 12:58:20 +08:00
Shelikhoo
e51710d144 Func: ListenTCP6 2016-06-12 12:46:26 +08:00
Shelikhoo
2fd963801c KCP: Added Dial func 2016-06-12 12:46:26 +08:00
Shelikhoo
e84d52263d KCP: Moved apply to KCPv 2016-06-12 12:46:26 +08:00
Shelikhoo
0f28c577ce KCP: Chiper generater 2016-06-12 12:46:26 +08:00
Shelikhoo
6f0b4aaf31 KCP: sorrgated Listener and conn 2016-06-12 12:46:26 +08:00
Shelikhoo
a8792b2b60 Added Config for KCP connetions 2016-06-12 12:46:26 +08:00
Shelikhoo
77eee3ed37 Added kcp json parser(By doing nothing) 2016-06-12 12:46:26 +08:00
Shelikhoo
12c40b7195 Renamed to kcpv avoid name conflict 2016-06-12 12:46:26 +08:00
Shelikhoo
63c1f2106d Added kcp related configs 2016-06-12 12:46:26 +08:00
Shelikhoo
8666d122f0 InboundHandlerMeta,OutboundHandlerMeta added KcpSupported bool to declare KCP support 2016-06-12 12:46:26 +08:00
v2ray
679d646571 only build for linux 2016-06-12 01:35:40 +02:00
v2ray
1c06fc216a allow redirection in dokodemo 2016-06-12 01:30:56 +02:00
v2ray
666dff02b0 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2016-06-11 22:54:26 +02:00
v2ray
098982d79a adjust error level 2016-06-11 22:54:23 +02:00
v2ray
09f7e8b61e meaningful error message 2016-06-11 22:52:37 +02:00
v2ray
ffce784dce comments 2016-06-11 13:29:33 +02:00
v2ray
b17edf907e enable connection reuse by default 2016-06-11 02:05:29 +02:00
v2ray
d9b59133cc Properly close inbound when no payload 2016-06-11 01:37:33 +02:00
v2ray
8a83a0b30e typo 2016-06-11 01:32:55 +02:00
v2ray
9c3f2ada47 update default response 2016-06-10 23:09:14 +02:00
v2ray
8b3875050d http response in blackhole 2016-06-10 23:01:17 +02:00
v2ray
e732ba62a6 unified config loader 2016-06-10 22:26:39 +02:00
Darien Raymond
3f7b70a465 Merge pull request #168 from xiaokangwang/fix.internal.CreateOutboundHandler.ErrorProxyNotFound
Fixed: internal.CreateOutboundHandler should return ErrorProxyNotFound if !found instead of ErrorNameExists
2016-06-09 11:03:18 +02:00
Shelikhoo
3b1f8b553b Fixed: internal.CreateOutboundHandler should return ErrorProxyNotFound if !found instead of ErrorNameExists 2016-06-09 09:38:44 +08:00
v2ray
774c8f5d5f fix refresh interval 2016-06-06 01:31:25 +02:00
v2ray
83c7e8491c fix conn reuse 2016-06-06 01:20:20 +02:00
v2ray
e878973def retry if vmess conn fails 2016-06-06 00:10:51 +02:00
v2ray
3376ea078d merge conflict 2016-06-05 23:42:16 +02:00
v2ray
08261e4f13 more china sites 2016-06-05 23:41:37 +02:00
v2ray
306ffabef0 merge conflict 2016-06-05 23:41:32 +02:00
v2ray
045e1dcc53 refine dynamic strategy 2016-06-05 23:39:38 +02:00
v2ray
aad10a75d3 typo 2016-06-05 23:37:28 +02:00
v2ray
5eae540e5c log access in socks and http 2016-06-05 15:02:15 +02:00
v2ray
309b64e376 take ich2Recycle as a parameter 2016-06-04 19:59:58 +02:00
v2ray
ea8f7e7506 simpilify updateUserHash method 2016-06-04 19:59:23 +02:00
v2ray
798c870069 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2016-06-04 17:48:51 +02:00
v2ray
372a32a66f more china sites 2016-06-04 17:48:23 +02:00
v2ray
50ca869929 organize handler metadata 2016-06-04 14:25:13 +02:00
v2ray
030fca10ba wait for test ready 2016-06-04 13:27:17 +02:00
v2ray
243e3ced89 update 2016-06-04 12:41:48 +02:00
v2ray
a4d76dc394 support using specific address 2016-06-04 00:38:22 +02:00
v2ray
6c31ff91e6 Merge branch 'master' of https://github.com/v2ray/v2ray-core 2016-06-03 20:21:53 +02:00
v2ray
4b92e6b25b update log 2016-06-03 20:21:46 +02:00
v2ray
e0c22860f1 more china sites 2016-06-03 12:47:22 +02:00
Darien Raymond
a2d8d55ba1 Update io_test.go 2016-06-03 11:40:50 +02:00
v2ray
0a7deabd46 remove unnecessary log 2016-06-02 23:23:04 +02:00
v2ray
47338fba1e timeout setting for freedom 2016-06-02 23:18:44 +02:00
v2ray
2f47074c98 release buffer 2016-06-02 22:23:05 +02:00
v2ray
f3975aafbf remove unnecessary log 2016-06-02 21:49:57 +02:00
v2ray
7a082ce63a update test 2016-06-02 21:48:49 +02:00
v2ray
40ebd1e9ae remove unused definition 2016-06-02 21:48:43 +02:00
v2ray
72fb5a256c send reuse option in header 2016-06-02 21:34:25 +02:00
v2ray
b9c88b673b unexpected eof 2016-06-02 21:20:58 +02:00
v2ray
ff0cb89efa simplify connection reuse settings 2016-06-02 20:52:52 +02:00
v2ray
9a8bc3fc3c async connection close 2016-06-02 02:40:46 +02:00
v2ray
dfe1ac1f2b Fix connection reuse 2016-06-02 02:20:53 +02:00
v2ray
a86cd36ad2 configuration for connection reuse 2016-06-02 01:49:25 +02:00
v2ray
6ce7b1d532 informational logs 2016-06-02 00:57:08 +02:00
v2ray
9713bf9adf completely fix detour config 2016-06-01 22:45:12 +02:00
v2ray
957eaf38db Assign detour config 2016-06-01 22:33:45 +02:00
v2ray
43f6998d31 discard bad connections 2016-06-01 22:09:34 +02:00
v2ray
4ec96efe84 smarter DNS query 2016-06-01 22:09:24 +02:00
v2ray
2c82f65189 return correct length in ReadFrom 2016-06-01 22:09:12 +02:00
v2ray
202ac9bb56 ReadFrom in BufferedWriter 2016-06-01 21:17:44 +02:00
v2ray
0fac2084c7 reusable connection 2016-05-31 00:21:41 +02:00
v2ray
3a6bf38686 remove validity map 2016-05-31 00:21:29 +02:00
v2ray
21ab26f41f missing function 2016-05-29 22:42:15 +02:00
v2ray
9457c4b349 clean up validity map 2016-05-29 22:42:03 +02:00
v2ray
da24d00367 reusable connection 2016-05-29 22:33:04 +02:00
v2ray
9b07ffd68f cleanup http proxy package 2016-05-29 16:46:31 +02:00
v2ray
b47c1ca609 get rid of annoying firewall warnings 2016-05-29 16:37:52 +02:00
v2ray
c3aa839227 add vscode task 2016-05-29 16:37:40 +02:00
v2ray
06aaaf970b update build tag settings due to plugin change 2016-05-29 16:37:30 +02:00
v2ray
8f4bd95bc3 fix default uuid and port 2016-05-28 14:09:01 +02:00
v2ray
3f9cb1136a allow dynamic type of user accounts 2016-05-28 13:44:11 +02:00
v2ray
87f664048b ready for 1.14 release 2016-05-27 17:45:02 +02:00
v2ray
07c3f2d7cd update help context 2016-05-27 17:44:56 +02:00
v2ray
3c4c14c89c allow local binary 2016-05-27 17:20:31 +02:00
v2ray
46f76e55e5 reorg chan reader 2016-05-25 22:36:52 +02:00
v2ray
e610faaff6 update default server address 2016-05-25 22:23:59 +02:00
v2ray
81cdaa0e4e Unify buffer allocation 2016-05-25 22:05:47 +02:00
v2ray
a2268d2a7b Allow customized target dir in build 2016-05-25 21:51:44 +02:00
v2ray
e9f0eea0d1 force install 2016-05-25 12:32:53 +02:00
v2ray
f48f51c6b4 bug fixes 2016-05-25 12:30:04 +02:00
v2ray
a4296f22df check version in install-release.sh 2016-05-25 12:27:40 +02:00
v2ray
3156c4586c Allow data stream passing through http proxy 2016-05-25 09:32:26 +02:00
v2ray
c75d840706 Remove serial.String 2016-05-24 22:41:51 +02:00
v2ray
444808a51a Remove Intxx interfaces 2016-05-24 22:15:46 +02:00
v2ray
ab39750ceb Remove serial.Bytes 2016-05-24 22:09:22 +02:00
v2ray
fc63f0432c simplify testing 2016-05-24 21:55:46 +02:00
v2ray
3582b9d869 move net/testing/assert into assert 2016-05-24 15:29:08 +02:00
v2ray
bbdc692a93 fix test break 2016-05-23 20:32:08 +02:00
v2ray
50957b9973 Fix build break 2016-05-23 20:25:24 +02:00
v2ray
47b2fafb32 Shorten StringLiteral 2016-05-23 20:23:40 +02:00
v2ray
cfdda19834 Shorten BytesLiteral 2016-05-23 20:21:23 +02:00
v2ray
5b23d25e35 address 2016-05-23 20:16:36 +02:00
v2ray
28cf3aa0c7 uint32 2016-05-23 20:16:31 +02:00
v2ray
ac58eed310 more china sites 2016-05-23 14:19:38 +02:00
v2ray
54cf3f75b1 daemon script 2016-05-23 01:21:03 +02:00
v2ray
0ea2678e72 Allow freedom to consume DNS settings 2016-05-22 22:30:21 +02:00
v2ray
bb503c6954 Static hosts in DNS server 2016-05-22 22:30:08 +02:00
294 changed files with 15334 additions and 10404 deletions

17
.github/ISSUE_TEMPLATE vendored Normal file
View File

@@ -0,0 +1,17 @@
提交 Issue 之前请先阅读 [Issue 指引](https://www.v2ray.com/zh_cn/chapter_01/issue.html),然后回答下面的问题,谢谢。
Please answer the following questions before submitting your issue. Thank you.
1) 你正在使用哪个版本的 V2Ray如果服务器和客户端使用了不同版本请注明
1) What version of V2Ray are you using?
2) 你的使用场景是什么?比如使用 Chrome 通过 Socks/VMess 代理观看 YouTube 视频。
2) What your scenario of using V2Ray? E.g., Watching YouTube videos in Chrome via Socks/VMess proxy.
3) 你看到的不正常的现象是什么?
3) What did you see?
4) 你期待看到的正确表现是怎样的?
4) What do you expected to see instead?
5) 请附上你的配置文件。
5) Please attach your configuration file.

View File

@@ -1,7 +1,7 @@
language: go
go:
- 1.6.2
- 1.6.3
before_install:
- go get golang.org/x/tools/cmd/cover

View File

@@ -1,6 +1,6 @@
// Place your settings in this file to overwrite default and user settings.
{
"go.buildFlags": ["-tags", "json"],
"go.lintFlags": ["-tags", "json"],
"go.vetFlags": ["-tags", "json"]
"editor.tabSize": 2,
"go.buildTags": "json"
}

30
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,30 @@
{
"version": "0.1.0",
"command": "go",
"isShellCommand": true,
"showOutput": "always",
"tasks": [
{
"taskName": "build",
"args": ["-tags", "json", "github.com/v2ray/v2ray-core/..."],
"isBuildCommand": true,
"problemMatcher": {
"owner": "go",
"fileLocation": ["relative", "${workspaceRoot}"],
"pattern": {
"regexp": "^([^:]+\\.go):(\\d+):(.*)",
"file": 1,
"line": 2,
"message": 3
}
}
},
{
"taskName": "test",
"args": ["-tags", "json", "github.com/v2ray/v2ray-core/..."],
"isBuildCommand": false
}
]
}

View File

@@ -1,11 +1,18 @@
# Project V2Ray
[![Join the chat at https://gitter.im/v2ray/v2ray-core](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/v2ray/v2ray-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/v2ray/v2ray-core.svg?branch=master)](https://travis-ci.org/v2ray/v2ray-core)
[![codecov.io](https://codecov.io/github/v2ray/v2ray-core/coverage.svg?branch=master)](https://codecov.io/github/v2ray/v2ray-core?branch=master)
[![Go Report](http://goreportcard.com/badge/v2ray/v2ray-core)](https://goreportcard.com/report/v2ray/v2ray-core)
[![GoDoc](https://godoc.org/github.com/v2ray/v2ray-core?status.svg)](https://godoc.org/github.com/v2ray/v2ray-core)
[![codebeat](https://codebeat.co/badges/f2354ca8-3e24-463d-a2e3-159af73b2477)](https://codebeat.co/projects/github-com-v2ray-v2ray-core)
[![Build Status][1]][2] [![codecov.io][3]][4] [![Go Report][5]][6] [![GoDoc][7]][8] [![codebeat][9]][10] [![Downloads][11]][12]
[1]: https://travis-ci.org/v2ray/v2ray-core.svg?branch=master "Build Status badge"
[2]: https://travis-ci.org/v2ray/v2ray-core "Travis-CI Build Status"
[3]: https://codecov.io/github/v2ray/v2ray-core/coverage.svg?branch=master "Coverage badge"
[4]: https://codecov.io/github/v2ray/v2ray-core?branch=master "Codecov Status"
[5]: https://goreportcard.com/badge/github.com/v2ray/v2ray-core "Go Report badge"
[6]: https://goreportcard.com/report/github.com/v2ray/v2ray-core "Go Report"
[7]: https://godoc.org/github.com/v2ray/v2ray-core?status.svg "GoDoc badge"
[8]: https://godoc.org/github.com/v2ray/v2ray-core "GoDoc"
[9]: https://codebeat.co/badges/f2354ca8-3e24-463d-a2e3-159af73b2477 "Codebeat badge"
[10]: https://codebeat.co/projects/github-com-v2ray-v2ray-core "Codebeat"
[11]: https://img.shields.io/github/downloads/v2ray/v2ray-core/total.svg?maxAge=2592000
[12]: https://github.com/v2ray/v2ray-core/releases
V2Ray 是一个模块化的代理软件包,它的目标是提供常用的代理软件模块,简化网络代理软件的开发。

View File

@@ -27,7 +27,7 @@ func NewDefaultDispatcher(space app.Space) *DefaultDispatcher {
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.ErrorMissingApplication
return app.ErrMissingApplication
}
this.ohm = space.GetApp(proxyman.APP_ID_OUTBOUND_MANAGER).(proxyman.OutboundHandlerManager)
@@ -68,7 +68,7 @@ func (this *DefaultDispatcher) DispatchToOutbound(destination v2net.Destination)
func (this *DefaultDispatcher) FilterPacketAndDispatch(destination v2net.Destination, link ray.OutboundRay, dispatcher proxy.OutboundHandler) {
payload, err := link.OutboundInput().Read()
if err != nil {
log.Info("DefaultDispatcher: No payload to dispatch, stopping now.")
log.Info("DefaultDispatcher: No payload towards ", destination, ", stopping now.")
link.OutboundInput().Release()
link.OutboundOutput().Release()
return

View File

@@ -1,9 +1,12 @@
package dns
import (
"net"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type Config struct {
Hosts map[string]net.IP
NameServers []v2net.Destination
}

View File

@@ -4,13 +4,16 @@ package dns
import (
"encoding/json"
"errors"
"net"
v2net "github.com/v2ray/v2ray-core/common/net"
)
func (this *Config) UnmarshalJSON(data []byte) error {
type JsonConfig struct {
Servers []v2net.AddressJson `json:"servers"`
Servers []v2net.AddressJson `json:"servers"`
Hosts map[string]v2net.AddressJson `json:"hosts"`
}
jsonConfig := new(JsonConfig)
if err := json.Unmarshal(data, jsonConfig); err != nil {
@@ -21,5 +24,15 @@ func (this *Config) UnmarshalJSON(data []byte) error {
this.NameServers[idx] = v2net.UDPDestination(server.Address, v2net.Port(53))
}
if jsonConfig.Hosts != nil {
this.Hosts = make(map[string]net.IP)
for domain, ip := range jsonConfig.Hosts {
if ip.Address.IsDomain() {
return errors.New(ip.Address.String() + " is not an IP.")
}
this.Hosts[domain] = ip.Address.IP()
}
}
return nil
}

View File

@@ -8,13 +8,11 @@ import (
. "github.com/v2ray/v2ray-core/app/dns"
v2net "github.com/v2ray/v2ray-core/common/net"
netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestConfigParsing(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rawJson := `{
"servers": ["8.8.8.8"]
@@ -24,7 +22,7 @@ func TestConfigParsing(t *testing.T) {
err := json.Unmarshal([]byte(rawJson), config)
assert.Error(err).IsNil()
assert.Int(len(config.NameServers)).Equals(1)
netassert.Destination(config.NameServers[0]).IsUDP()
netassert.Address(config.NameServers[0].Address()).Equals(v2net.IPAddress([]byte{8, 8, 8, 8}))
netassert.Port(config.NameServers[0].Port()).Equals(v2net.Port(53))
assert.Destination(config.NameServers[0]).IsUDP()
assert.Address(config.NameServers[0].Address()).Equals(v2net.IPAddress([]byte{8, 8, 8, 8}))
assert.Port(config.NameServers[0].Port()).Equals(v2net.Port(53))
}

View File

@@ -1,16 +1,16 @@
package dns
import (
"math/rand"
"net"
"sync"
"time"
"github.com/v2ray/v2ray-core/app/dispatcher"
"github.com/v2ray/v2ray-core/common/alloc"
"github.com/v2ray/v2ray-core/common/dice"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/transport/hub"
"github.com/v2ray/v2ray-core/transport/internet/udp"
"github.com/miekg/dns"
)
@@ -21,6 +21,10 @@ const (
CleanupThreshold = 512
)
var (
pseudoDestination = v2net.UDPDestination(v2net.LocalHostIP, v2net.Port(53))
)
type ARecord struct {
IPs []net.IP
Expire time.Time
@@ -39,7 +43,7 @@ type UDPNameServer struct {
sync.Mutex
address v2net.Destination
requests map[uint16]*PendingRequest
udpServer *hub.UDPServer
udpServer *udp.UDPServer
nextCleanup time.Time
}
@@ -47,7 +51,7 @@ func NewUDPNameServer(address v2net.Destination, dispatcher dispatcher.PacketDis
s := &UDPNameServer{
address: address,
requests: make(map[uint16]*PendingRequest),
udpServer: hub.NewUDPServer(dispatcher),
udpServer: udp.NewUDPServer(dispatcher),
}
return s
}
@@ -80,13 +84,13 @@ func (this *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 {
}
for {
id = uint16(rand.Intn(65536))
id = uint16(dice.Roll(65536))
if _, found := this.requests[id]; found {
continue
}
log.Debug("DNS: Add pending request id ", id)
this.requests[id] = &PendingRequest{
expire: time.Now().Add(time.Second * 16),
expire: time.Now().Add(time.Second * 8),
response: response,
}
break
@@ -139,15 +143,13 @@ func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc
close(request.response)
}
func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord {
response := make(chan *ARecord, 1)
func (this *UDPNameServer) BuildQueryA(domain string, id uint16) *alloc.Buffer {
buffer := alloc.NewBuffer()
msg := new(dns.Msg)
msg.Id = this.AssignUnusedID(response)
msg.Id = id
msg.RecursionDesired = true
msg.Question = []dns.Question{
dns.Question{
{
Name: dns.Fqdn(domain),
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
@@ -156,8 +158,32 @@ func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord {
writtenBuffer, _ := msg.PackBuffer(buffer.Value)
buffer.Slice(0, len(writtenBuffer))
fakeDestination := v2net.UDPDestination(v2net.LocalHostIP, v2net.Port(53))
this.udpServer.Dispatch(fakeDestination, this.address, buffer, this.HandleResponse)
return buffer
}
func (this *UDPNameServer) DispatchQuery(payload *alloc.Buffer) {
this.udpServer.Dispatch(pseudoDestination, this.address, payload, this.HandleResponse)
}
func (this *UDPNameServer) QueryA(domain string) <-chan *ARecord {
response := make(chan *ARecord, 1)
id := this.AssignUnusedID(response)
this.DispatchQuery(this.BuildQueryA(domain, id))
go func() {
for i := 0; i < 2; i++ {
time.Sleep(time.Second)
this.Lock()
_, found := this.requests[id]
this.Unlock()
if found {
this.DispatchQuery(this.BuildQueryA(domain, id))
} else {
break
}
}
}()
return response
}

View File

@@ -23,6 +23,7 @@ type DomainRecord struct {
type CacheServer struct {
sync.RWMutex
space app.Space
hosts map[string]net.IP
records map[string]*DomainRecord
servers []NameServer
}
@@ -31,11 +32,12 @@ func NewCacheServer(space app.Space, config *Config) *CacheServer {
server := &CacheServer{
records: make(map[string]*DomainRecord),
servers: make([]NameServer, len(config.NameServers)),
hosts: config.Hosts,
}
space.InitializeApplication(func() error {
if !space.HasApp(dispatcher.APP_ID) {
log.Error("DNS: Dispatcher is not found in the space.")
return app.ErrorMissingApplication
return app.ErrMissingApplication
}
dispatcher := space.GetApp(dispatcher.APP_ID).(dispatcher.PacketDispatcher)
@@ -46,6 +48,9 @@ func NewCacheServer(space app.Space, config *Config) *CacheServer {
server.servers[idx] = NewUDPNameServer(ns, dispatcher)
}
}
if len(config.NameServers) == 0 {
server.servers = append(server.servers, &LocalNameServer{})
}
return nil
})
return server
@@ -67,6 +72,10 @@ func (this *CacheServer) GetCached(domain string) []net.IP {
}
func (this *CacheServer) Get(domain string) []net.IP {
if ip, found := this.hosts[domain]; found {
return []net.IP{ip}
}
domain = dns.Fqdn(domain)
ips := this.GetCached(domain)
if ips != nil {

View File

@@ -10,19 +10,28 @@ import (
. "github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/proxyman"
v2net "github.com/v2ray/v2ray-core/common/net"
netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
"github.com/v2ray/v2ray-core/proxy"
"github.com/v2ray/v2ray-core/proxy/freedom"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
"github.com/v2ray/v2ray-core/transport/internet"
)
func TestDnsAdd(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
space := app.NewSpace()
outboundHandlerManager := proxyman.NewDefaultOutboundHandlerManager()
outboundHandlerManager.SetDefaultHandler(&freedom.FreedomConnection{})
outboundHandlerManager.SetDefaultHandler(
freedom.NewFreedomConnection(
&freedom.Config{},
space,
&proxy.OutboundHandlerMeta{
Address: v2net.AnyIP,
StreamSettings: &internet.StreamSettings{
Type: internet.StreamConnectionTypeRawTCP,
},
}))
space.BindApp(proxyman.APP_ID_OUTBOUND_MANAGER, outboundHandlerManager)
space.BindApp(dispatcher.APP_ID, dispatchers.NewDefaultDispatcher(space))
@@ -37,5 +46,5 @@ func TestDnsAdd(t *testing.T) {
ips := server.Get(domain)
assert.Int(len(ips)).Equals(1)
netassert.IP(ips[0].To4()).Equals(net.IP([]byte{127, 0, 0, 1}))
assert.IP(ips[0].To4()).Equals(net.IP([]byte{127, 0, 0, 1}))
}

View File

@@ -9,7 +9,7 @@ type ConfigObjectCreator func([]byte) (interface{}, error)
var (
configCache map[string]ConfigObjectCreator
ErrorRouterNotFound = errors.New("Router not found.")
ErrRouterNotFound = errors.New("Router not found.")
)
func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
@@ -21,7 +21,7 @@ func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
func CreateRouterConfig(strategy string, data []byte) (interface{}, error) {
creator, found := configCache[strategy]
if !found {
return nil, ErrorRouterNotFound
return nil, ErrRouterNotFound
}
return creator(data)
}

View File

@@ -33,5 +33,5 @@ func CreateRouter(name string, rawConfig interface{}, space app.Space) (Router,
if factory, found := routerCache[name]; found {
return factory.Create(rawConfig, space)
}
return nil, ErrorRouterNotFound
return nil, ErrRouterNotFound
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,18 +6,17 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/app/router/rules"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestChinaIPJson(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "chinaip",
"outboundTag": "x"
}`))
assert.StringLiteral(rule.Tag).Equals("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

View File

@@ -6,7 +6,6 @@ import (
. "github.com/v2ray/v2ray-core/app/router/rules"
v2net "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
@@ -15,7 +14,7 @@ func makeDestination(ip string) v2net.Destination {
}
func TestChinaIP(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rule := NewChinaIPRule("tag")
assert.Bool(rule.Apply(makeDestination("121.14.1.189"))).IsTrue() // sina.com.cn

View File

@@ -66,6 +66,7 @@ func init() {
anySubDomain + "51" + dotLa,
anySubDomain + "51credit" + dotCom,
anySubDomain + "51cto" + dotCom,
anySubDomain + "51jingying" + dotCom,
anySubDomain + "51job" + dotCom,
anySubDomain + "51jobcdn" + dotCom,
anySubDomain + "51wendang" + dotCom,
@@ -120,6 +121,7 @@ func init() {
anySubDomain + "bitauto" + dotCom,
anySubDomain + "bitautoimg" + dotCom,
anySubDomain + "bobo" + dotCom,
anySubDomain + "bootcss" + dotCom,
anySubDomain + "btcfans" + dotCom,
anySubDomain + "caiyunapp" + dotCom,
anySubDomain + "ccb" + dotCom,
@@ -135,8 +137,10 @@ func init() {
anySubDomain + "chinacache" + dotNet,
anySubDomain + "chinahr" + dotCom,
anySubDomain + "chinamobile" + dotCom,
anySubDomain + "chinapay" + dotCom,
anySubDomain + "chinatranslation" + dotNet,
anySubDomain + "chinaz" + dotCom,
anySubDomain + "chiphell" + dotCom,
anySubDomain + "chouti" + dotCom,
anySubDomain + "chuangxin" + dotCom,
anySubDomain + "chuansong" + dotMe,
@@ -149,6 +153,7 @@ func init() {
anySubDomain + "cnepub" + dotCom,
anySubDomain + "cnzz" + dotCom,
anySubDomain + "coding" + dotNet,
anySubDomain + "coolapk" + dotCom,
anySubDomain + "cqvip" + dotCom,
anySubDomain + "csbew" + dotCom,
anySubDomain + "csdn" + dotNet,
@@ -180,7 +185,9 @@ func init() {
anySubDomain + "emarbox" + dotCom,
anySubDomain + "eoeandroid" + dotCom,
anySubDomain + "etao" + dotCom,
anySubDomain + "excelhome" + dotNet,
anySubDomain + "fanli" + dotCom,
anySubDomain + "feng" + dotCom,
anySubDomain + "fengniao" + dotCom,
anySubDomain + "fhldns" + dotCom,
anySubDomain + "foxmail" + dotCom,
@@ -188,6 +195,7 @@ func init() {
anySubDomain + "geetest" + dotCom,
anySubDomain + "geilicdn" + dotCom,
anySubDomain + "getui" + dotCom,
anySubDomain + "google-analytics" + dotCom,
anySubDomain + "growingio" + dotCom,
anySubDomain + "gtags" + dotNet,
anySubDomain + "gwdang" + dotCom,
@@ -196,6 +204,7 @@ func init() {
anySubDomain + "haosou" + dotCom,
anySubDomain + "hdslb" + dotCom,
anySubDomain + "henha" + dotCom,
anySubDomain + "henkuai" + dotCom,
anySubDomain + "hexun" + dotCom,
anySubDomain + "hichina" + dotCom,
anySubDomain + "huanqiu" + dotCom,
@@ -213,6 +222,7 @@ func init() {
anySubDomain + "ifeng" + dotCom,
anySubDomain + "ifengimg" + dotCom,
anySubDomain + "ijinshan" + dotCom,
anySubDomain + "ikafan" + dotCom,
anySubDomain + "imedao" + dotCom,
anySubDomain + "imgo" + dotTv,
anySubDomain + "imooc" + dotCom,
@@ -227,6 +237,7 @@ func init() {
anySubDomain + "it168" + dotCom,
anySubDomain + "it610" + dotCom,
anySubDomain + "iteye" + dotCom,
anySubDomain + "ithome" + dotCom,
anySubDomain + "itjuzi" + dotCom,
anySubDomain + "jandan" + dotNet,
anySubDomain + "jd" + dotCom,
@@ -240,6 +251,7 @@ func init() {
anySubDomain + "jikexueyuan" + dotCom,
anySubDomain + "jisuanke" + dotCom,
anySubDomain + "jmstatic" + dotCom,
anySubDomain + "jsdelivr" + dotNet,
anySubDomain + "jstv" + dotCom,
anySubDomain + "jumei" + dotCom,
anySubDomain + "jyimg" + dotCom,
@@ -303,6 +315,7 @@ func init() {
anySubDomain + "mogucdn" + dotCom,
anySubDomain + "mogujie" + dotCom,
anySubDomain + "mop" + dotCom,
anySubDomain + "mscbsc" + dotCom,
anySubDomain + "mukewang" + dotCom,
anySubDomain + "mydrivers" + dotCom,
anySubDomain + "myshow360" + dotNet,
@@ -319,6 +332,7 @@ func init() {
anySubDomain + "onlinesjtu" + dotCom,
anySubDomain + "oschina" + dotNet,
anySubDomain + "paipai" + dotCom,
anySubDomain + "pcbeta" + dotCom,
anySubDomain + "pchome" + dotNet,
anySubDomain + "pingan" + dotCom,
anySubDomain + "pingplusplus" + dotCom,
@@ -345,6 +359,7 @@ func init() {
anySubDomain + "qunarzz" + dotCom,
anySubDomain + "qzone" + dotCom,
anySubDomain + "renren" + dotCom,
anySubDomain + "ruanmei" + dotCom,
anySubDomain + "ruby-china" + dotOrg,
anySubDomain + "sandai" + dotNet,
anySubDomain + "sanguosha" + dotCom,
@@ -352,6 +367,7 @@ func init() {
anySubDomain + "segmentfault" + dotCom,
anySubDomain + "sf-express" + dotCom,
anySubDomain + "sharejs" + dotCom,
anySubDomain + "shmetro" + dotCom,
anySubDomain + "shutcm" + dotCom,
anySubDomain + "simei8" + dotCom,
anySubDomain + "sina" + dotCom,
@@ -391,6 +407,7 @@ func init() {
anySubDomain + "tudouui" + dotCom,
anySubDomain + "tuicool" + dotCom,
anySubDomain + "tuniu" + dotCom,
anySubDomain + "tutuapp" + dotCom,
anySubDomain + "u17" + dotCom,
anySubDomain + "useso" + dotCom,
anySubDomain + "unionpay" + dotCom,
@@ -401,14 +418,19 @@ func init() {
anySubDomain + "v5875" + dotCom,
anySubDomain + "vamaker" + dotCom,
anySubDomain + "vancl" + dotCom,
anySubDomain + "vcimg" + dotCom,
anySubDomain + "vip" + dotCom,
anySubDomain + "wallstreetcn" + dotCom,
anySubDomain + "wandoujia" + dotCom,
anySubDomain + "wdjimg" + dotCom,
anySubDomain + "weand" + dotCom,
anySubDomain + "webterren" + dotCom,
anySubDomain + "weibo" + dotCom,
anySubDomain + "weicaifu" + dotCom,
anySubDomain + "weidian" + dotCom,
anySubDomain + "weiphone" + dotCom,
anySubDomain + "weiphone" + dotNet,
anySubDomain + "weixing" + dotCom,
anySubDomain + "weiyun" + dotCom,
anySubDomain + "wonnder" + dotCom,
anySubDomain + "worktile" + dotCom,
@@ -451,6 +473,7 @@ func init() {
anySubDomain + "zampda" + dotNet,
anySubDomain + "zastatic" + dotCom,
anySubDomain + "zbjimg" + dotCom,
anySubDomain + "zdfans" + dotCom,
anySubDomain + "zhenai" + dotCom,
anySubDomain + "zhanqi" + dotTv,
anySubDomain + "zhaopin" + dotCom,

View File

@@ -6,18 +6,17 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/app/router/rules"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestChinaSitesJson(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "chinasites",
"outboundTag": "y"
}`))
assert.StringLiteral(rule.Tag).Equals("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()

View File

@@ -5,7 +5,6 @@ import (
. "github.com/v2ray/v2ray-core/app/router/rules"
v2net "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
@@ -14,7 +13,7 @@ func makeDomainDestination(domain string) v2net.Destination {
}
func TestChinaSites(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rule := NewChinaSitesRule("tag")
assert.Bool(rule.Apply(makeDomainDestination("v.qq.com"))).IsTrue()

View File

@@ -3,9 +3,9 @@ package rules
import (
"net"
"regexp"
"strings"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
)
type Condition interface {
@@ -63,12 +63,12 @@ func (this *AnyCondition) Len() int {
}
type PlainDomainMatcher struct {
pattern serial.StringLiteral
pattern string
}
func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
return &PlainDomainMatcher{
pattern: serial.StringLiteral(pattern),
pattern: pattern,
}
}
@@ -76,8 +76,8 @@ func (this *PlainDomainMatcher) Apply(dest v2net.Destination) bool {
if !dest.Address().IsDomain() {
return false
}
domain := serial.StringLiteral(dest.Address().Domain())
return domain.Contains(this.pattern)
domain := dest.Address().Domain()
return strings.Contains(domain, this.pattern)
}
type RegexpDomainMatcher struct {
@@ -98,8 +98,8 @@ func (this *RegexpDomainMatcher) Apply(dest v2net.Destination) bool {
if !dest.Address().IsDomain() {
return false
}
domain := serial.StringLiteral(dest.Address().Domain())
return this.pattern.MatchString(domain.ToLower().String())
domain := dest.Address().Domain()
return this.pattern.MatchString(strings.ToLower(domain))
}
type CIDRMatcher struct {

View File

@@ -8,9 +8,9 @@ import (
"strings"
router "github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/collect"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
)
type JsonRule struct {
@@ -21,10 +21,10 @@ type JsonRule struct {
func parseFieldRule(msg json.RawMessage) (*Rule, error) {
type RawFieldRule struct {
JsonRule
Domain *serial.StringLiteralList `json:"domain"`
IP *serial.StringLiteralList `json:"ip"`
Port *v2net.PortRange `json:"port"`
Network *v2net.NetworkList `json:"network"`
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)
@@ -37,14 +37,14 @@ func parseFieldRule(msg json.RawMessage) (*Rule, error) {
anyCond := NewAnyCondition()
for _, rawDomain := range *(rawFieldRule.Domain) {
var matcher Condition
if strings.HasPrefix(rawDomain.String(), "regexp:") {
rawMatcher, err := NewRegexpDomainMatcher(rawDomain.String()[7:])
if strings.HasPrefix(rawDomain, "regexp:") {
rawMatcher, err := NewRegexpDomainMatcher(rawDomain[7:])
if err != nil {
return nil, err
}
matcher = rawMatcher
} else {
matcher = NewPlainDomainMatcher(rawDomain.String())
matcher = NewPlainDomainMatcher(rawDomain)
}
anyCond.Add(matcher)
}
@@ -54,7 +54,7 @@ func parseFieldRule(msg json.RawMessage) (*Rule, error) {
if rawFieldRule.IP != nil && rawFieldRule.IP.Len() > 0 {
anyCond := NewAnyCondition()
for _, ipStr := range *(rawFieldRule.IP) {
cidrMatcher, err := NewCIDRMatcher(ipStr.String())
cidrMatcher, err := NewCIDRMatcher(ipStr)
if err != nil {
log.Error("Router: Invalid IP range in router rule: ", err)
return nil, err
@@ -128,10 +128,10 @@ func init() {
Rules: make([]*Rule, len(jsonConfig.RuleList)),
DomainStrategy: DomainAsIs,
}
domainStrategy := serial.StringLiteral(jsonConfig.DomainStrategy).ToLower()
if domainStrategy.String() == "alwaysip" {
domainStrategy := strings.ToLower(jsonConfig.DomainStrategy)
if domainStrategy == "alwaysip" {
config.DomainStrategy = AlwaysUseIP
} else if domainStrategy.String() == "ipifnonmatch" {
} else if domainStrategy == "ipifnonmatch" {
config.DomainStrategy = UseIPIfNonMatch
}
for idx, rawRule := range jsonConfig.RuleList {

View File

@@ -7,12 +7,11 @@ import (
. "github.com/v2ray/v2ray-core/app/router/rules"
v2net "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestDomainRule(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "field",
@@ -33,7 +32,7 @@ func TestDomainRule(t *testing.T) {
}
func TestIPRule(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rule := ParseRule([]byte(`{
"type": "field",

View File

@@ -2,59 +2,34 @@ package rules
import (
"errors"
"time"
"github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/dns"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/collect"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
)
var (
ErrorInvalidRule = errors.New("Invalid Rule")
ErrorNoRuleApplicable = errors.New("No rule applicable")
ErrInvalidRule = errors.New("Invalid Rule")
ErrNoRuleApplicable = errors.New("No rule applicable")
)
type cacheEntry struct {
tag string
err error
validUntil time.Time
}
func newCacheEntry(tag string, err error) *cacheEntry {
this := &cacheEntry{
tag: tag,
err: err,
}
this.Extend()
return this
}
func (this *cacheEntry) IsValid() bool {
return this.validUntil.Before(time.Now())
}
func (this *cacheEntry) Extend() {
this.validUntil = time.Now().Add(time.Hour)
}
type Router struct {
config *RouterRuleConfig
cache *collect.ValidityMap
cache *RoutingTable
dnsServer dns.Server
}
func NewRouter(config *RouterRuleConfig, space app.Space) *Router {
r := &Router{
config: config,
cache: collect.NewValidityMap(3600),
cache: NewRoutingTable(),
}
space.InitializeApplication(func() error {
if !space.HasApp(dns.APP_ID) {
log.Error("DNS: Router is not found in the space.")
return app.ErrorMissingApplication
return app.ErrMissingApplication
}
r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
return nil
@@ -104,18 +79,18 @@ func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, erro
}
}
return "", ErrorNoRuleApplicable
return "", ErrNoRuleApplicable
}
func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
rawEntry := this.cache.Get(dest)
if rawEntry == nil {
destStr := dest.String()
found, tag, err := this.cache.Get(destStr)
if !found {
tag, err := this.takeDetourWithoutCache(dest)
this.cache.Set(dest, newCacheEntry(tag, err))
this.cache.Set(destStr, tag, err)
return tag, err
}
entry := rawEntry.(*cacheEntry)
return entry.tag, entry.err
return tag, err
}
type RouterFactory struct {

View File

@@ -11,12 +11,11 @@ import (
"github.com/v2ray/v2ray-core/app/router"
. "github.com/v2ray/v2ray-core/app/router/rules"
v2net "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestSimpleRouter(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
config := &RouterRuleConfig{
Rules: []*Rule{
@@ -37,5 +36,5 @@ func TestSimpleRouter(t *testing.T) {
tag, err := r.TakeDetour(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80))
assert.Error(err).IsNil()
assert.StringLiteral(tag).Equals("test")
assert.String(tag).Equals("test")
}

View File

@@ -0,0 +1,70 @@
package rules
import (
"sync"
"time"
)
type RoutingEntry struct {
tag string
err error
expire time.Time
}
func (this *RoutingEntry) Extend() {
this.expire = time.Now().Add(time.Hour)
}
func (this *RoutingEntry) Expired() bool {
return this.expire.Before(time.Now())
}
type RoutingTable struct {
sync.RWMutex
table map[string]*RoutingEntry
}
func NewRoutingTable() *RoutingTable {
return &RoutingTable{
table: make(map[string]*RoutingEntry),
}
}
func (this *RoutingTable) Cleanup() {
this.Lock()
defer this.Unlock()
for key, value := range this.table {
if value.Expired() {
delete(this.table, key)
}
}
}
func (this *RoutingTable) Set(destination string, tag string, err error) {
this.Lock()
defer this.Unlock()
entry := &RoutingEntry{
tag: tag,
err: err,
}
entry.Extend()
this.table[destination] = entry
if len(this.table) > 1000 {
go this.Cleanup()
}
}
func (this *RoutingTable) Get(destination string) (bool, string, error) {
this.RLock()
defer this.RUnlock()
entry, found := this.table[destination]
if !found {
return false, "", nil
}
entry.Extend()
return true, entry.tag, entry.err
}

View File

@@ -7,7 +7,7 @@ import (
)
var (
ErrorMissingApplication = errors.New("App: Failed to found one or more applications.")
ErrMissingApplication = errors.New("App: Failed to found one or more applications.")
)
type ID int

View File

@@ -1,7 +1,11 @@
// Package alloc provides a light-weight memory allocation mechanism.
package alloc
import (
"hash"
"io"
"github.com/v2ray/v2ray-core/common/serial"
)
const (
@@ -18,12 +22,23 @@ type Buffer struct {
offset int
}
func CreateBuffer(container []byte, parent *BufferPool) *Buffer {
b := new(Buffer)
b.head = container
b.pool = parent
b.Value = b.head[defaultOffset:]
b.offset = defaultOffset
return b
}
// Release recycles the buffer into an internal buffer pool.
func (b *Buffer) Release() {
if b == nil {
if b == nil || b.head == nil {
return
}
b.pool.Free(b)
if b.pool != nil {
b.pool.Free(b)
}
b.head = nil
b.Value = nil
b.pool = nil
@@ -37,6 +52,12 @@ func (b *Buffer) Clear() *Buffer {
return b
}
func (b *Buffer) Reset() *Buffer {
b.offset = defaultOffset
b.Value = b.head
return b
}
// AppendBytes appends one or more bytes to the end of the buffer.
func (b *Buffer) AppendBytes(bytes ...byte) *Buffer {
b.Value = append(b.Value, bytes...)
@@ -49,11 +70,22 @@ func (b *Buffer) Append(data []byte) *Buffer {
return b
}
// AppendString appends a given string to the end of the buffer.
func (b *Buffer) AppendString(s string) *Buffer {
b.Value = append(b.Value, s...)
return b
}
func (b *Buffer) AppendUint16(v uint16) *Buffer {
b.Value = serial.Uint16ToBytes(v, b.Value)
return b
}
func (b *Buffer) AppendUint32(v uint32) *Buffer {
b.Value = serial.Uint32ToBytes(v, b.Value)
return b
}
// Prepend prepends bytes in front of the buffer. Caller must ensure total bytes prepended is
// no more than 16 bytes.
func (b *Buffer) Prepend(data []byte) *Buffer {
@@ -62,6 +94,28 @@ func (b *Buffer) Prepend(data []byte) *Buffer {
return b
}
func (b *Buffer) PrependBytes(data ...byte) *Buffer {
return b.Prepend(data)
}
func (b *Buffer) PrependUint16(v uint16) *Buffer {
b.SliceBack(2)
serial.Uint16ToBytes(v, b.Value[:0])
return b
}
func (b *Buffer) PrependUint32(v uint32) *Buffer {
b.SliceBack(4)
serial.Uint32ToBytes(v, b.Value[:0])
return b
}
func (b *Buffer) PrependHash(h hash.Hash) *Buffer {
b.SliceBack(h.Size())
h.Sum(b.Value[:0])
return b
}
// Bytes returns the content bytes of this Buffer.
func (b *Buffer) Bytes() []byte {
return b.Value
@@ -86,7 +140,7 @@ func (b *Buffer) SliceFrom(from int) *Buffer {
func (b *Buffer) SliceBack(offset int) *Buffer {
newoffset := b.offset - offset
if newoffset < 0 {
newoffset = 0
panic("Negative buffer offset.")
}
b.Value = b.head[newoffset : b.offset+len(b.Value)]
b.offset = newoffset
@@ -159,3 +213,19 @@ func NewBuffer() *Buffer {
func NewLargeBuffer() *Buffer {
return largePool.Allocate()
}
func NewBufferWithSize(size int) *Buffer {
if size <= SmallBufferSize {
return NewSmallBuffer()
}
if size <= BufferSize {
return NewBuffer()
}
return NewLargeBuffer()
}
func NewLocalBuffer(size int) *Buffer {
return CreateBuffer(make([]byte, size), nil)
}

View File

@@ -16,7 +16,7 @@ func NewBufferPool(bufferSize, poolSize int) *BufferPool {
New: func() interface{} { return make([]byte, bufferSize) },
},
}
for i := 0; i < poolSize/2; i++ {
for i := 0; i < poolSize; i++ {
pool.chain <- make([]byte, bufferSize)
}
return pool
@@ -29,12 +29,7 @@ func (p *BufferPool) Allocate() *Buffer {
default:
b = p.allocator.Get().([]byte)
}
return &Buffer{
head: b,
pool: p,
Value: b[defaultOffset:],
offset: defaultOffset,
}
return CreateBuffer(b, p)
}
func (p *BufferPool) Free(buffer *Buffer) {
@@ -50,10 +45,11 @@ func (p *BufferPool) Free(buffer *Buffer) {
}
const (
SmallBufferSize = 1600 - defaultOffset
BufferSize = 8*1024 - defaultOffset
LargeBufferSize = 64*1024 - defaultOffset
)
var smallPool = NewBufferPool(1024, 64)
var mediumPool = NewBufferPool(8*1024, 128)
var largePool = NewBufferPool(64*1024, 64)
var smallPool = NewBufferPool(1600, 1024)
var mediumPool = NewBufferPool(8*1024, 256)
var largePool = NewBufferPool(64*1024, 32)

View File

@@ -4,12 +4,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/alloc"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestBufferClear(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
buffer := NewBuffer().Clear()
defer buffer.Release()
@@ -23,7 +22,7 @@ func TestBufferClear(t *testing.T) {
}
func TestBufferIsFull(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
buffer := NewBuffer()
defer buffer.Release()
@@ -35,7 +34,7 @@ func TestBufferIsFull(t *testing.T) {
}
func TestBufferPrepend(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
buffer := NewBuffer().Clear()
defer buffer.Release()
@@ -51,11 +50,11 @@ func TestBufferPrepend(t *testing.T) {
}
func TestBufferString(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
buffer := NewBuffer().Clear()
defer buffer.Release()
buffer.AppendString("Test String")
assert.String(buffer).Equals("Test String")
assert.String(buffer.String()).Equals("Test String")
}

View File

@@ -0,0 +1,12 @@
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,6 +1,6 @@
// +build json
package serial
package collect
import (
"encoding/json"
@@ -8,17 +8,17 @@ import (
"strings"
)
func (this *StringLiteralList) UnmarshalJSON(data []byte) error {
func (this *StringList) UnmarshalJSON(data []byte) error {
var strarray []string
if err := json.Unmarshal(data, &strarray); err == nil {
*this = *NewStringLiteralList(strarray)
*this = *NewStringList(strarray)
return nil
}
var rawstr string
if err := json.Unmarshal(data, &rawstr); err == nil {
strlist := strings.Split(rawstr, ",")
*this = *NewStringLiteralList(strlist)
*this = *NewStringList(strlist)
return nil
}
return errors.New("Unknown format of a string list: " + string(data))

View File

@@ -1,21 +1,20 @@
// +build json
package serial_test
package collect_test
import (
"encoding/json"
"testing"
. "github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
. "github.com/v2ray/v2ray-core/common/collect"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestStringListUnmarshalError(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rawJson := `1234`
list := new(StringLiteralList)
list := new(StringList)
err := json.Unmarshal([]byte(rawJson), list)
assert.Error(err).IsNotNil()
}

View File

@@ -1,72 +0,0 @@
package collect
import (
"sync"
"sync/atomic"
"github.com/v2ray/v2ray-core/common/serial"
)
type Validity interface {
IsValid() bool
}
type entry struct {
key string
value Validity
}
type ValidityMap struct {
sync.RWMutex
cache map[string]Validity
opCount int32
}
func NewValidityMap(cleanupIntervalSec int) *ValidityMap {
instance := &ValidityMap{
cache: make(map[string]Validity),
}
return instance
}
func (this *ValidityMap) cleanup() {
entry2Remove := make([]entry, 0, 128)
this.RLock()
for key, value := range this.cache {
if !value.IsValid() {
entry2Remove = append(entry2Remove, entry{
key: key,
value: value,
})
}
}
this.RUnlock()
for _, entry := range entry2Remove {
if !entry.value.IsValid() {
this.Lock()
delete(this.cache, entry.key)
this.Unlock()
}
}
}
func (this *ValidityMap) Set(key serial.String, value Validity) {
this.Lock()
this.cache[key.String()] = value
this.Unlock()
opCount := atomic.AddInt32(&this.opCount, 1)
if opCount > 1000 {
atomic.StoreInt32(&this.opCount, 0)
go this.cleanup()
}
}
func (this *ValidityMap) Get(key serial.String) Validity {
this.RLock()
defer this.RUnlock()
if value, found := this.cache[key.String()]; found {
return value
}
return nil
}

View File

@@ -7,7 +7,8 @@ import (
)
var (
ErrorAlreadyReleased = errors.New("Object already released.")
ErrObjectReleased = errors.New("Object already released.")
ErrBadConfiguration = errors.New("Bad configuration.")
)
// Releasable interface is for those types that can release its members.

View File

@@ -5,11 +5,15 @@ import (
"crypto/cipher"
)
// NewAesDecryptionStream creates a new AES encryption stream based on given key and IV.
// Caller must ensure the length of key and IV is either 16, 24 or 32 bytes.
func NewAesDecryptionStream(key []byte, iv []byte) cipher.Stream {
aesBlock, _ := aes.NewCipher(key)
return cipher.NewCFBDecrypter(aesBlock, iv)
}
// NewAesEncryptionStream creates a new AES description stream based on given key and IV.
// Caller must ensure the length of key and IV is either 16, 24 or 32 bytes.
func NewAesEncryptionStream(key []byte, iv []byte) cipher.Stream {
aesBlock, _ := aes.NewCipher(key)
return cipher.NewCFBEncrypter(aesBlock, iv)

View File

@@ -6,6 +6,8 @@ import (
"github.com/v2ray/v2ray-core/common/crypto/internal"
)
// NewChaCha20Stream creates a new Chacha20 encryption/descryption stream based on give key and IV.
// Caller must ensure the length of key is 32 bytes, and length of IV is either 8 or 12 bytes.
func NewChaCha20Stream(key []byte, iv []byte) cipher.Stream {
return internal.NewChaCha20Stream(key, iv, 20)
}

View File

@@ -6,7 +6,6 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/crypto"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
@@ -19,7 +18,7 @@ func mustDecodeHex(s string) []byte {
}
func TestChaCha20Stream(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var cases = []struct {
key []byte
@@ -58,7 +57,7 @@ func TestChaCha20Stream(t *testing.T) {
}
func TestChaCha20Decoding(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
key := make([]byte, 32)
rand.Read(key)

View File

@@ -21,7 +21,7 @@ func NewCryptionReader(stream cipher.Stream, reader io.Reader) *CryptionReader {
func (this *CryptionReader) Read(data []byte) (int, error) {
if this.reader == nil {
return 0, common.ErrorAlreadyReleased
return 0, common.ErrObjectReleased
}
nBytes, err := this.reader.Read(data)
if nBytes > 0 {
@@ -49,7 +49,7 @@ func NewCryptionWriter(stream cipher.Stream, writer io.Writer) *CryptionWriter {
func (this *CryptionWriter) Write(data []byte) (int, error) {
if this.writer == nil {
return 0, common.ErrorAlreadyReleased
return 0, common.ErrObjectReleased
}
this.stream.XORKeyStream(data, data)
return this.writer.Write(data)

View File

@@ -5,12 +5,11 @@ import (
"github.com/v2ray/v2ray-core/common/alloc"
. "github.com/v2ray/v2ray-core/common/io"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestBufferedReader(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
content := alloc.NewLargeBuffer()
len := content.Len()

View File

@@ -22,6 +22,28 @@ func NewBufferedWriter(rawWriter io.Writer) *BufferedWriter {
}
}
func (this *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
this.Lock()
defer this.Unlock()
if this.writer == nil {
return 0, io.EOF
}
totalBytes := int64(0)
for {
nBytes, err := this.buffer.FillFrom(reader)
totalBytes += int64(nBytes)
if err != nil {
if err == io.EOF {
return totalBytes, nil
}
return totalBytes, err
}
this.FlushWithoutLock()
}
}
func (this *BufferedWriter) Write(b []byte) (int, error) {
this.Lock()
defer this.Unlock()
@@ -35,7 +57,7 @@ func (this *BufferedWriter) Write(b []byte) (int, error) {
}
nBytes, _ := this.buffer.Write(b)
if this.buffer.IsFull() {
go this.Flush()
this.FlushWithoutLock()
}
return nBytes, nil
}
@@ -43,10 +65,15 @@ func (this *BufferedWriter) Write(b []byte) (int, error) {
func (this *BufferedWriter) Flush() error {
this.Lock()
defer this.Unlock()
if this.writer == nil {
return io.EOF
}
return this.FlushWithoutLock()
}
func (this *BufferedWriter) FlushWithoutLock() error {
defer this.buffer.Clear()
for !this.buffer.IsEmpty() {
nBytes, err := this.writer.Write(this.buffer.Value)

View File

@@ -5,12 +5,11 @@ import (
"github.com/v2ray/v2ray-core/common/alloc"
. "github.com/v2ray/v2ray-core/common/io"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestBufferedWriter(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
content := alloc.NewLargeBuffer().Clear()

48
common/io/chain_writer.go Normal file
View File

@@ -0,0 +1,48 @@
package io
import (
"io"
"sync"
"github.com/v2ray/v2ray-core/common/alloc"
)
type ChainWriter struct {
sync.Mutex
writer Writer
}
func NewChainWriter(writer Writer) *ChainWriter {
return &ChainWriter{
writer: writer,
}
}
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
}
err := this.writer.Write(buffer)
if err != nil {
return 0, err
}
return size, nil
}
func (this *ChainWriter) Release() {
this.Lock()
this.writer.Release()
this.writer = nil
this.Unlock()
}

64
common/io/chan_reader.go Normal file
View File

@@ -0,0 +1,64 @@
package io
import (
"io"
"sync"
"github.com/v2ray/v2ray-core/common/alloc"
)
type ChanReader struct {
sync.Mutex
stream Reader
current *alloc.Buffer
eof bool
}
func NewChanReader(stream Reader) *ChanReader {
this := &ChanReader{
stream: stream,
}
this.Fill()
return this
}
// @Private
func (this *ChanReader) Fill() {
b, err := this.stream.Read()
this.current = b
if err != nil {
this.eof = true
this.current = nil
}
}
func (this *ChanReader) Read(b []byte) (int, error) {
if this.eof {
return 0, io.EOF
}
this.Lock()
defer this.Unlock()
if this.current == nil {
this.Fill()
if this.eof {
return 0, io.EOF
}
}
nBytes, err := this.current.Read(b)
if this.current.IsEmpty() {
this.current.Release()
this.current = nil
}
return nBytes, err
}
func (this *ChanReader) Release() {
this.Lock()
defer this.Unlock()
this.eof = true
this.current.Release()
this.current = nil
this.stream = nil
}

View File

@@ -7,17 +7,6 @@ import (
"github.com/v2ray/v2ray-core/common/alloc"
)
// ReadFrom reads from a reader and put all content to a buffer.
// If buffer is nil, ReadFrom creates a new normal buffer.
func ReadFrom(reader io.Reader, buffer *alloc.Buffer) (*alloc.Buffer, error) {
if buffer == nil {
buffer = alloc.NewBuffer()
}
nBytes, err := reader.Read(buffer.Value)
buffer.Slice(0, nBytes)
return buffer, err
}
// Reader extends io.Reader with alloc.Buffer.
type Reader interface {
common.Releasable
@@ -42,7 +31,12 @@ func NewAdaptiveReader(reader io.Reader) *AdaptiveReader {
// Read implements Reader.Read().
func (this *AdaptiveReader) Read() (*alloc.Buffer, error) {
buffer, err := ReadFrom(this.reader, this.allocate())
buffer := this.allocate().Clear()
_, err := buffer.FillFrom(this.reader)
if err != nil {
buffer.Release()
return nil, err
}
if buffer.Len() >= alloc.BufferSize {
this.allocate = alloc.NewLargeBuffer
@@ -50,10 +44,6 @@ func (this *AdaptiveReader) Read() (*alloc.Buffer, error) {
this.allocate = alloc.NewBuffer
}
if err != nil {
buffer.Release()
return nil, err
}
return buffer, nil
}

View File

@@ -6,12 +6,11 @@ import (
"github.com/v2ray/v2ray-core/common/alloc"
. "github.com/v2ray/v2ray-core/common/io"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestAdaptiveReader(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rawContent := make([]byte, 1024*1024)

View File

@@ -20,6 +20,7 @@ func Pipe(reader Reader, writer Writer) error {
err = writer.Write(buffer)
if err != nil {
log.Debug("IO: Pipe exits as ", err)
buffer.Release()
return err
}
}

View File

@@ -7,12 +7,11 @@ import (
"github.com/v2ray/v2ray-core/common/alloc"
. "github.com/v2ray/v2ray-core/common/io"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestAdaptiveWriter(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
lb := alloc.NewLargeBuffer()
rand.Read(lb.Value)

View File

@@ -0,0 +1,61 @@
// +build json
package loader
import (
"encoding/json"
"github.com/v2ray/v2ray-core/common/log"
)
type JSONConfigLoader struct {
*BaseConfigLoader
idKey string
configKey string
}
func NewJSONConfigLoader(idKey string, configKey string) *JSONConfigLoader {
return &JSONConfigLoader{
idKey: idKey,
configKey: configKey,
BaseConfigLoader: NewBaseConfigLoader(),
}
}
func (this *JSONConfigLoader) LoadWithID(raw []byte, id string) (interface{}, error) {
config, err := this.CreateConfig(id)
if err != nil {
return nil, err
}
if err := json.Unmarshal(raw, config); err != nil {
return nil, err
}
return config, nil
}
func (this *JSONConfigLoader) Load(raw []byte) (interface{}, error) {
var obj map[string]json.RawMessage
if err := json.Unmarshal(raw, &obj); err != nil {
return nil, err
}
rawID, found := obj[this.idKey]
if !found {
log.Error(this.idKey, " not found in JSON content.")
return nil, ErrConfigIDKeyNotFound
}
var id string
if err := json.Unmarshal(rawID, &id); err != nil {
return nil, err
}
rawConfig := json.RawMessage(raw)
if len(this.configKey) > 0 {
configValue, found := obj[this.configKey]
if !found {
log.Error(this.configKey, " not found in JSON content.")
return nil, ErrConfigIDKeyNotFound
}
rawConfig = configValue
}
return this.LoadWithID([]byte(rawConfig), id)
}

47
common/loader/loader.go Normal file
View File

@@ -0,0 +1,47 @@
package loader
import (
"errors"
)
var (
ErrConfigIDKeyNotFound = errors.New("Config ID key is not found.")
ErrConfigIDExists = errors.New("Config ID already exists.")
ErrUnknownConfigID = errors.New("Unknown config ID.")
)
type ConfigCreator func() interface{}
type ConfigLoader interface {
RegisterCreator(string, ConfigCreator) error
CreateConfig(string) (interface{}, error)
Load([]byte) (interface{}, error)
LoadWithID([]byte, string) (interface{}, error)
}
type BaseConfigLoader struct {
creators map[string]ConfigCreator
}
func NewBaseConfigLoader() *BaseConfigLoader {
return &BaseConfigLoader{
creators: make(map[string]ConfigCreator),
}
}
func (this *BaseConfigLoader) RegisterCreator(id string, creator ConfigCreator) error {
if _, found := this.creators[id]; found {
return ErrConfigIDExists
}
this.creators[id] = creator
return nil
}
func (this *BaseConfigLoader) CreateConfig(id string) (interface{}, error) {
creator, found := this.creators[id]
if !found {
return nil, ErrUnknownConfigID
}
return creator(), nil
}

View File

@@ -2,7 +2,6 @@ package log
import (
"github.com/v2ray/v2ray-core/common/log/internal"
"github.com/v2ray/v2ray-core/common/serial"
)
// AccessStatus is the status of an access request from clients.
@@ -29,7 +28,7 @@ func InitAccessLogger(file string) error {
}
// Access writes an access log.
func Access(from, to serial.String, status AccessStatus, reason serial.String) {
func Access(from, to interface{}, status AccessStatus, reason interface{}) {
accessLoggerInstance.Log(&internal.AccessLog{
From: from,
To: to,

View File

@@ -2,15 +2,35 @@ package internal
import (
"fmt"
"strings"
"github.com/v2ray/v2ray-core/common"
"github.com/v2ray/v2ray-core/common/alloc"
"github.com/v2ray/v2ray-core/common/serial"
)
func InterfaceToString(value interface{}) string {
if value == nil {
return " "
}
switch value := value.(type) {
case string:
return value
case *string:
return *value
case fmt.Stringer:
return value.String()
case error:
return value.Error()
case []byte:
return serial.BytesToHexString(value)
default:
return fmt.Sprint(value)
}
}
type LogEntry interface {
common.Releasable
serial.String
fmt.Stringer
}
type ErrorLog struct {
@@ -26,33 +46,19 @@ func (this *ErrorLog) Release() {
}
func (this *ErrorLog) String() string {
b := alloc.NewSmallBuffer().Clear()
defer b.Release()
b.AppendString(this.Prefix)
for _, value := range this.Values {
switch typedVal := value.(type) {
case string:
b.AppendString(typedVal)
case *string:
b.AppendString(*typedVal)
case serial.String:
b.AppendString(typedVal.String())
case error:
b.AppendString(typedVal.Error())
default:
b.AppendString(fmt.Sprint(value))
}
values := make([]string, len(this.Values)+1)
values[0] = this.Prefix
for i, value := range this.Values {
values[i+1] = InterfaceToString(value)
}
return b.String()
return strings.Join(values, "")
}
type AccessLog struct {
From serial.String
To serial.String
From interface{}
To interface{}
Status string
Reason serial.String
Reason interface{}
}
func (this *AccessLog) Release() {
@@ -62,8 +68,5 @@ func (this *AccessLog) Release() {
}
func (this *AccessLog) String() string {
b := alloc.NewSmallBuffer().Clear()
defer b.Release()
return b.AppendString(this.From.String()).AppendString(" ").AppendString(this.Status).AppendString(" ").AppendString(this.To.String()).AppendString(" ").AppendString(this.Reason.String()).String()
return strings.Join([]string{InterfaceToString(this.From), this.Status, InterfaceToString(this.To), InterfaceToString(this.Reason)}, " ")
}

View File

@@ -4,24 +4,22 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/log/internal"
"github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestAccessLog(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
entry := &AccessLog{
From: serial.StringLiteral("test_from"),
To: serial.StringLiteral("test_to"),
From: "test_from",
To: "test_to",
Status: "Accepted",
Reason: serial.StringLiteral("test_reason"),
Reason: "test_reason",
}
entryStr := entry.String()
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("test_from"))
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("test_to"))
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("test_reason"))
assert.StringLiteral(entryStr).Contains(serial.StringLiteral("Accepted"))
assert.String(entryStr).Contains("test_from")
assert.String(entryStr).Contains("test_to")
assert.String(entryStr).Contains("test_reason")
assert.String(entryStr).Contains("Accepted")
}

View File

@@ -3,12 +3,15 @@ package internal
import (
"log"
"os"
"time"
"github.com/v2ray/v2ray-core/common/platform"
"github.com/v2ray/v2ray-core/common/signal"
)
type LogWriter interface {
Log(LogEntry)
Close()
}
type NoOpLogWriter struct {
@@ -18,13 +21,18 @@ func (this *NoOpLogWriter) Log(entry LogEntry) {
entry.Release()
}
func (this *NoOpLogWriter) Close() {
}
type StdOutLogWriter struct {
logger *log.Logger
cancel *signal.CancelSignal
}
func NewStdOutLogWriter() LogWriter {
return &StdOutLogWriter{
logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
cancel: signal.NewCloseSignal(),
}
}
@@ -33,10 +41,15 @@ func (this *StdOutLogWriter) Log(log LogEntry) {
log.Release()
}
func (this *StdOutLogWriter) Close() {
time.Sleep(500 * time.Millisecond)
}
type FileLogWriter struct {
queue chan string
logger *log.Logger
file *os.File
cancel *signal.CancelSignal
}
func (this *FileLogWriter) Log(log LogEntry) {
@@ -56,9 +69,12 @@ func (this *FileLogWriter) run() {
}
this.logger.Print(entry + platform.LineSeparator())
}
this.cancel.Done()
}
func (this *FileLogWriter) Close() {
close(this.queue)
<-this.cancel.WaitForDone()
this.file.Close()
}
@@ -71,6 +87,7 @@ func NewFileLogWriter(path string) (*FileLogWriter, error) {
queue: make(chan string, 16),
logger: log.New(file, "", log.Ldate|log.Ltime),
file: file,
cancel: signal.NewCloseSignal(),
}
go logger.run()
return logger, nil

View File

@@ -90,3 +90,8 @@ func Error(v ...interface{}) {
Values: v,
})
}
func Close() {
streamLoggerInstance.Close()
accessLoggerInstance.Close()
}

View File

@@ -4,11 +4,12 @@ import (
"net"
"github.com/v2ray/v2ray-core/common/log"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/common/predicate"
)
var (
LocalHostIP = IPAddress([]byte{127, 0, 0, 1})
AnyIP = IPAddress([]byte{0, 0, 0, 0})
)
// Address represents a network address to be communicated with. It may be an IP address or domain
@@ -42,7 +43,7 @@ func IPAddress(ip []byte) Address {
var addr ipv4Address = [4]byte{ip[0], ip[1], ip[2], ip[3]}
return &addr
case net.IPv6len:
if serial.BytesLiteral(ip[0:10]).All(0) && serial.BytesLiteral(ip[10:12]).All(0xff) {
if predicate.BytesAll(ip[0:10], 0) && predicate.BytesAll(ip[10:12], 0xff) {
return IPAddress(ip[12:16])
}
var addr ipv6Address = [16]byte{
@@ -132,12 +133,22 @@ func (this *ipv6Address) Equals(another Address) bool {
if !ok {
return false
}
for idx, v := range *this {
if anotherIPv6[idx] != v {
return false
}
}
return true
return this[0] == anotherIPv6[0] &&
this[1] == anotherIPv6[1] &&
this[2] == anotherIPv6[2] &&
this[3] == anotherIPv6[3] &&
this[4] == anotherIPv6[4] &&
this[5] == anotherIPv6[5] &&
this[6] == anotherIPv6[6] &&
this[7] == anotherIPv6[7] &&
this[8] == anotherIPv6[8] &&
this[9] == anotherIPv6[9] &&
this[10] == anotherIPv6[10] &&
this[11] == anotherIPv6[11] &&
this[12] == anotherIPv6[12] &&
this[13] == anotherIPv6[13] &&
this[14] == anotherIPv6[14] &&
this[15] == anotherIPv6[15]
}
type domainAddress string

View File

@@ -8,12 +8,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestIPParsing(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rawJson := "\"8.8.8.8\""
var address AddressJson
@@ -25,7 +24,7 @@ func TestIPParsing(t *testing.T) {
}
func TestDomainParsing(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rawJson := "\"v2ray.com\""
var address AddressJson
@@ -33,11 +32,11 @@ func TestDomainParsing(t *testing.T) {
assert.Error(err).IsNil()
assert.Bool(address.Address.IsIPv4()).IsFalse()
assert.Bool(address.Address.IsDomain()).IsTrue()
assert.StringLiteral(address.Address.Domain()).Equals("v2ray.com")
assert.String(address.Address.Domain()).Equals("v2ray.com")
}
func TestInvalidAddressJson(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
rawJson := "1234"
var address AddressJson

View File

@@ -5,26 +5,24 @@ import (
"testing"
v2net "github.com/v2ray/v2ray-core/common/net"
v2netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestIPv4Address(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
ip := []byte{byte(1), byte(2), byte(3), byte(4)}
addr := v2net.IPAddress(ip)
v2netassert.Address(addr).IsIPv4()
v2netassert.Address(addr).IsNotIPv6()
v2netassert.Address(addr).IsNotDomain()
assert.Address(addr).IsIPv4()
assert.Address(addr).IsNotIPv6()
assert.Address(addr).IsNotDomain()
assert.Bytes(addr.IP()).Equals(ip)
assert.String(addr).Equals("1.2.3.4")
assert.Address(addr).EqualsString("1.2.3.4")
}
func TestIPv6Address(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
ip := []byte{
byte(1), byte(2), byte(3), byte(4),
@@ -34,15 +32,15 @@ func TestIPv6Address(t *testing.T) {
}
addr := v2net.IPAddress(ip)
v2netassert.Address(addr).IsIPv6()
v2netassert.Address(addr).IsNotIPv4()
v2netassert.Address(addr).IsNotDomain()
assert.Bytes(addr.IP()).Equals(ip)
assert.String(addr).Equals("[102:304:102:304:102:304:102:304]")
assert.Address(addr).IsIPv6()
assert.Address(addr).IsNotIPv4()
assert.Address(addr).IsNotDomain()
assert.IP(addr.IP()).Equals(net.IP(ip))
assert.Address(addr).EqualsString("[102:304:102:304:102:304:102:304]")
}
func TestIPv4Asv6(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
ip := []byte{
byte(0), byte(0), byte(0), byte(0),
byte(0), byte(0), byte(0), byte(0),
@@ -50,49 +48,49 @@ func TestIPv4Asv6(t *testing.T) {
byte(1), byte(2), byte(3), byte(4),
}
addr := v2net.IPAddress(ip)
assert.String(addr).Equals("1.2.3.4")
assert.Address(addr).EqualsString("1.2.3.4")
}
func TestDomainAddress(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
domain := "v2ray.com"
addr := v2net.DomainAddress(domain)
v2netassert.Address(addr).IsDomain()
v2netassert.Address(addr).IsNotIPv6()
v2netassert.Address(addr).IsNotIPv4()
assert.StringLiteral(addr.Domain()).Equals(domain)
assert.String(addr).Equals("v2ray.com")
assert.Address(addr).IsDomain()
assert.Address(addr).IsNotIPv6()
assert.Address(addr).IsNotIPv4()
assert.String(addr.Domain()).Equals(domain)
assert.Address(addr).EqualsString("v2ray.com")
}
func TestNetIPv4Address(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
ip := net.IPv4(1, 2, 3, 4)
addr := v2net.IPAddress(ip)
v2netassert.Address(addr).IsIPv4()
assert.String(addr).Equals("1.2.3.4")
assert.Address(addr).IsIPv4()
assert.Address(addr).EqualsString("1.2.3.4")
}
func TestIPv4AddressEquals(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
addr := v2net.IPAddress([]byte{1, 2, 3, 4})
assert.Bool(addr.Equals(nil)).IsFalse()
assert.Address(addr).NotEquals(nil)
addr2 := v2net.IPAddress([]byte{1, 2, 3, 4})
assert.Bool(addr.Equals(addr2)).IsTrue()
assert.Address(addr).Equals(addr2)
addr3 := v2net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6})
assert.Bool(addr.Equals(addr3)).IsFalse()
assert.Address(addr).NotEquals(addr3)
addr4 := v2net.IPAddress([]byte{1, 2, 3, 5})
assert.Bool(addr.Equals(addr4)).IsFalse()
assert.Address(addr).NotEquals(addr4)
}
func TestIPv6AddressEquals(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
addr := v2net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6})
assert.Bool(addr.Equals(nil)).IsFalse()
@@ -108,7 +106,7 @@ func TestIPv6AddressEquals(t *testing.T) {
}
func TestDomainAddressEquals(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
addr := v2net.DomainAddress("v2ray.com")
assert.Bool(addr.Equals(nil)).IsFalse()

View File

@@ -4,31 +4,29 @@ import (
"testing"
v2net "github.com/v2ray/v2ray-core/common/net"
v2netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestTCPDestination(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
dest := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
v2netassert.Destination(dest).IsTCP()
v2netassert.Destination(dest).IsNotUDP()
assert.String(dest).Equals("tcp:1.2.3.4:80")
assert.Destination(dest).IsTCP()
assert.Destination(dest).IsNotUDP()
assert.Destination(dest).EqualsString("tcp:1.2.3.4:80")
}
func TestUDPDestination(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
dest := v2net.UDPDestination(v2net.IPAddress([]byte{0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}), 53)
v2netassert.Destination(dest).IsNotTCP()
v2netassert.Destination(dest).IsUDP()
assert.String(dest).Equals("udp:[2001:4860:4860::8888]:53")
assert.Destination(dest).IsNotTCP()
assert.Destination(dest).IsUDP()
assert.Destination(dest).EqualsString("udp:[2001:4860:4860::8888]:53")
}
func TestTCPDestinationEquals(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
dest := v2net.TCPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
assert.Bool(dest.Equals(nil)).IsFalse()
@@ -44,7 +42,7 @@ func TestTCPDestinationEquals(t *testing.T) {
}
func TestUDPDestinationEquals(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
dest := v2net.UDPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}), 80)
assert.Bool(dest.Equals(nil)).IsFalse()

View File

@@ -5,18 +5,19 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func parseCIDR(str string) *net.IPNet {
_, ipNet, err := net.ParseCIDR(str)
assert.Error(err).IsNil()
if err != nil {
panic(err)
}
return ipNet
}
func TestIPNet(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
ipNet := NewIPNet()
ipNet.Add(parseCIDR(("0.0.0.0/8")))

View File

@@ -1,7 +1,9 @@
package net
import (
"github.com/v2ray/v2ray-core/common/serial"
"strings"
"github.com/v2ray/v2ray-core/common/collect"
)
const (
@@ -10,24 +12,31 @@ const (
// UDPNetwork represents the UDP network.
UDPNetwork = Network("udp")
// KCPNetwork represents the KCP network.
KCPNetwork = Network("kcp")
)
// Network represents a communication network on internet.
type Network serial.StringLiteral
type Network string
func (this Network) AsList() *NetworkList {
list := NetworkList([]Network{this})
return &list
}
func (this Network) String() string {
return string(this)
}
// NetworkList is a list of Networks.
type NetworkList []Network
// NewNetworkList construsts a NetWorklist from the given StringListeralList.
func NewNetworkList(networks serial.StringLiteralList) NetworkList {
func NewNetworkList(networks collect.StringList) NetworkList {
list := NetworkList(make([]Network, networks.Len()))
for idx, network := range networks {
list[idx] = Network(network.TrimSpace().ToLower())
list[idx] = Network(strings.ToLower(strings.TrimSpace(network)))
}
return list
}

View File

@@ -5,11 +5,11 @@ package net
import (
"encoding/json"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/common/collect"
)
func (this *NetworkList) UnmarshalJSON(data []byte) error {
var strlist serial.StringLiteralList
var strlist collect.StringList
if err := json.Unmarshal(data, &strlist); err != nil {
return err
}

View File

@@ -7,12 +7,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestArrayNetworkList(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var list NetworkList
err := json.Unmarshal([]byte("[\"Tcp\"]"), &list)
@@ -22,7 +21,7 @@ func TestArrayNetworkList(t *testing.T) {
}
func TestStringNetworkList(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var list NetworkList
err := json.Unmarshal([]byte("\"TCP, ip\""), &list)
@@ -32,7 +31,7 @@ func TestStringNetworkList(t *testing.T) {
}
func TestInvalidNetworkJson(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var list NetworkList
err := json.Unmarshal([]byte("0"), &list)

View File

@@ -8,24 +8,24 @@ import (
)
var (
// ErrorInvalidPortRage indicates an error during port range parsing.
ErrorInvalidPortRange = errors.New("Invalid port range.")
// ErrInvalidPortRage indicates an error during port range parsing.
ErrInvalidPortRange = errors.New("Invalid port range.")
)
// Port represents a network port in TCP and UDP protocol.
type Port serial.Uint16Literal
type Port uint16
// PortFromBytes converts a byte array to a Port, assuming bytes are in big endian order.
// @unsafe Caller must ensure that the byte array has at least 2 elements.
func PortFromBytes(port []byte) Port {
return Port(serial.BytesLiteral(port).Uint16Value())
return Port(serial.BytesToUint16(port))
}
// PortFromInt converts an integer to a Port.
// @error when the integer is not positive or larger then 65535
func PortFromInt(v int) (Port, error) {
if v <= 0 || v > 65535 {
return Port(0), ErrorInvalidPortRange
return Port(0), ErrInvalidPortRange
}
return Port(v), nil
}
@@ -35,7 +35,7 @@ func PortFromInt(v int) (Port, error) {
func PortFromString(s string) (Port, error) {
v, err := strconv.Atoi(s)
if err != nil {
return Port(0), ErrorInvalidPortRange
return Port(0), ErrInvalidPortRange
}
return PortFromInt(v)
}
@@ -46,13 +46,13 @@ func (this Port) Value() uint16 {
}
// Bytes returns the correspoding bytes of this Port, in big endian order.
func (this Port) Bytes() []byte {
return serial.Uint16Literal(this).Bytes()
func (this Port) Bytes(b []byte) []byte {
return serial.Uint16ToBytes(this.Value(), b)
}
// String returns the string presentation of this Port.
func (this Port) String() string {
return serial.Uint16Literal(this).String()
return serial.Uint16ToString(this.Value())
}
// PortRange represents a range of ports.

View File

@@ -26,7 +26,7 @@ func parseStringPort(data []byte) (Port, Port, error) {
}
pair := strings.SplitN(s, "-", 2)
if len(pair) == 0 {
return Port(0), Port(0), ErrorInvalidPortRange
return Port(0), Port(0), ErrInvalidPortRange
}
if len(pair) == 1 {
port, err := PortFromString(pair[0])
@@ -59,11 +59,11 @@ func (this *PortRange) UnmarshalJSON(data []byte) error {
this.To = to
if this.From > this.To {
log.Error("Invalid port range ", this.From, " -> ", this.To)
return ErrorInvalidPortRange
return ErrInvalidPortRange
}
return nil
}
log.Error("Invalid port range: ", string(data))
return ErrorInvalidPortRange
return ErrInvalidPortRange
}

View File

@@ -7,12 +7,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestIntPort(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("1234"), &portRange)
@@ -23,18 +22,18 @@ func TestIntPort(t *testing.T) {
}
func TestOverRangeIntPort(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("70000"), &portRange)
assert.Error(err).Equals(ErrorInvalidPortRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("-1"), &portRange)
assert.Error(err).Equals(ErrorInvalidPortRange)
assert.Error(err).Equals(ErrInvalidPortRange)
}
func TestSingleStringPort(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"1234\""), &portRange)
@@ -45,7 +44,7 @@ func TestSingleStringPort(t *testing.T) {
}
func TestStringPairPort(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"1234-5678\""), &portRange)
@@ -56,18 +55,18 @@ func TestStringPairPort(t *testing.T) {
}
func TestOverRangeStringPort(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
var portRange PortRange
err := json.Unmarshal([]byte("\"65536\""), &portRange)
assert.Error(err).Equals(ErrorInvalidPortRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"70000-80000\""), &portRange)
assert.Error(err).Equals(ErrorInvalidPortRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"1-90000\""), &portRange)
assert.Error(err).Equals(ErrorInvalidPortRange)
assert.Error(err).Equals(ErrInvalidPortRange)
err = json.Unmarshal([]byte("\"700-600\""), &portRange)
assert.Error(err).Equals(ErrorInvalidPortRange)
assert.Error(err).Equals(ErrInvalidPortRange)
}

View File

@@ -4,12 +4,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestPortRangeContains(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
portRange := &PortRange{
From: Port(53),

View File

@@ -1,67 +0,0 @@
package assert
import (
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/testing/assert"
)
func Address(value v2net.Address) *AddressSubject {
return &AddressSubject{value: value}
}
type AddressSubject struct {
assert.Subject
value v2net.Address
}
func (subject *AddressSubject) Named(name string) *AddressSubject {
subject.Subject.Named(name)
return subject
}
func (subject *AddressSubject) DisplayString() string {
return subject.Subject.DisplayString(subject.value.String())
}
func (subject *AddressSubject) Equals(another v2net.Address) {
if !subject.value.Equals(another) {
subject.Fail(subject.DisplayString(), "equals to", another)
}
}
func (subject *AddressSubject) IsIPv4() {
if !subject.value.IsIPv4() {
subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("an IPv4 address"))
}
}
func (subject *AddressSubject) IsNotIPv4() {
if subject.value.IsIPv4() {
subject.Fail(subject.DisplayString(), "is not", serial.StringLiteral("an IPv4 address"))
}
}
func (subject *AddressSubject) IsIPv6() {
if !subject.value.IsIPv6() {
subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("an IPv6 address"))
}
}
func (subject *AddressSubject) IsNotIPv6() {
if subject.value.IsIPv6() {
subject.Fail(subject.DisplayString(), "is not", serial.StringLiteral("an IPv6 address"))
}
}
func (subject *AddressSubject) IsDomain() {
if !subject.value.IsDomain() {
subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("a domain address"))
}
}
func (subject *AddressSubject) IsNotDomain() {
if subject.value.IsDomain() {
subject.Fail(subject.DisplayString(), "is not", serial.StringLiteral("a domain address"))
}
}

View File

@@ -1,49 +0,0 @@
package assert
import (
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/testing/assert"
)
func Destination(value v2net.Destination) *DestinationSubject {
return &DestinationSubject{value: value}
}
type DestinationSubject struct {
assert.Subject
value v2net.Destination
}
func (this *DestinationSubject) Named(name string) *DestinationSubject {
this.Subject.Named(name)
return this
}
func (this *DestinationSubject) DisplayString() string {
return this.Subject.DisplayString(this.value.String())
}
func (this *DestinationSubject) IsTCP() {
if !this.value.IsTCP() {
this.Fail(this.DisplayString(), "is", serial.StringLiteral("a TCP destination"))
}
}
func (this *DestinationSubject) IsNotTCP() {
if this.value.IsTCP() {
this.Fail(this.DisplayString(), "is not", serial.StringLiteral("a TCP destination"))
}
}
func (this *DestinationSubject) IsUDP() {
if !this.value.IsUDP() {
this.Fail(this.DisplayString(), "is", serial.StringLiteral("a UDP destination"))
}
}
func (this *DestinationSubject) IsNotUDP() {
if this.value.IsUDP() {
this.Fail(this.DisplayString(), "is not", serial.StringLiteral("a UDP destination"))
}
}

View File

@@ -1,39 +0,0 @@
package assert
import (
"bytes"
"net"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/testing/assert"
)
func IP(value net.IP) *IPSubject {
return &IPSubject{value: value}
}
type IPSubject struct {
assert.Subject
value net.IP
}
func (subject *IPSubject) Named(name string) *IPSubject {
subject.Subject.Named(name)
return subject
}
func (subject *IPSubject) DisplayString() string {
return subject.Subject.DisplayString(subject.value.String())
}
func (subject *IPSubject) IsNil() {
if subject.value != nil {
subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("nil"))
}
}
func (subject *IPSubject) Equals(ip net.IP) {
if !bytes.Equal([]byte(subject.value), []byte(ip)) {
subject.Fail(subject.DisplayString(), "equals to", ip)
}
}

View File

@@ -1,49 +0,0 @@
package assert
import (
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/testing/assert"
)
func Port(value v2net.Port) *PortSubject {
return &PortSubject{value: value}
}
type PortSubject struct {
assert.Subject
value v2net.Port
}
func (subject *PortSubject) Named(name string) *PortSubject {
subject.Subject.Named(name)
return subject
}
func (subject *PortSubject) DisplayString() string {
return subject.Subject.DisplayString(subject.value.String())
}
func (subject *PortSubject) Equals(expectation v2net.Port) {
if subject.value.Value() != expectation.Value() {
subject.Fail(subject.DisplayString(), "is equal to", expectation)
}
}
func (subject *PortSubject) GreaterThan(expectation v2net.Port) {
if subject.value.Value() <= expectation.Value() {
subject.Fail(subject.DisplayString(), "is greater than", expectation)
}
}
func (subject *PortSubject) LessThan(expectation v2net.Port) {
if subject.value.Value() >= expectation.Value() {
subject.Fail(subject.DisplayString(), "is less than", expectation)
}
}
func (subject *PortSubject) IsValid() {
if subject.value == 0 {
subject.Fail(subject.DisplayString(), "is", serial.StringLiteral("a valid port"))
}
}

View File

@@ -6,5 +6,5 @@ import (
)
func PickPort() v2net.Port {
return v2net.Port(30000 + dice.Roll(5000))
return v2net.Port(30000 + dice.Roll(20000))
}

View File

@@ -4,12 +4,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/net"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestTimeOutSettings(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
reader := NewTimeOutReader(8, nil)
assert.Int(reader.GetTimeOut()).Equals(8)

View File

@@ -0,0 +1,10 @@
package predicate
func BytesAll(array []byte, b byte) bool {
for _, v := range array {
if v != b {
return false
}
}
return true
}

View File

@@ -1,4 +1,5 @@
package protocol
type Account interface {
Equals(Account) bool
}

View File

@@ -1,25 +0,0 @@
package protocol
import (
"io"
)
type RequestEncoder interface {
EncodeRequestHeader(*RequestHeader, io.Writer)
EncodeRequestBody(io.Writer) io.Writer
}
type RequestDecoder interface {
DecodeRequestHeader(io.Reader) (*RequestHeader, error)
DecodeRequestBody(io.Reader) io.Reader
}
type ResponseEncoder interface {
EncodeResponseHeader(*ResponseHeader, io.Writer)
EncodeResponseBody(io.Writer) io.Writer
}
type ResponseDecoder interface {
DecodeResponseHeader(io.Reader) (*ResponseHeader, error)
DecodeResponseBody(io.Reader) io.Reader
}

View File

@@ -5,6 +5,6 @@ import (
)
var (
ErrorInvalidUser = errors.New("Invalid user.")
ErrorInvalidVersion = errors.New("Invalid version.")
ErrInvalidUser = errors.New("Invalid user.")
ErrInvalidVersion = errors.New("Invalid version.")
)

View File

@@ -2,7 +2,6 @@ package protocol
import (
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/common/uuid"
)
@@ -13,14 +12,23 @@ const (
RequestCommandUDP = RequestCommand(0x02)
)
const (
RequestOptionChunkStream = RequestOption(0x01)
)
type RequestOption byte
func (this RequestOption) IsChunkStream() bool {
return (this & RequestOptionChunkStream) == RequestOptionChunkStream
const (
RequestOptionChunkStream = RequestOption(0x01)
RequestOptionConnectionReuse = RequestOption(0x02)
)
func (this RequestOption) Has(option RequestOption) bool {
return (this & option) == option
}
func (this *RequestOption) Set(option RequestOption) {
*this = (*this | option)
}
func (this *RequestOption) Clear(option RequestOption) {
*this = (*this & (^option))
}
type RequestHeader struct {
@@ -39,9 +47,28 @@ func (this *RequestHeader) Destination() v2net.Destination {
return v2net.TCPDestination(this.Address, this.Port)
}
type ResponseOption byte
const (
ResponseOptionConnectionReuse = ResponseOption(1)
)
func (this *ResponseOption) Set(option ResponseOption) {
*this = (*this | option)
}
func (this ResponseOption) Has(option ResponseOption) bool {
return (this | option) == option
}
func (this *ResponseOption) Clear(option ResponseOption) {
*this = (*this & (^option))
}
type ResponseCommand interface{}
type ResponseHeader struct {
Option ResponseOption
Command ResponseCommand
}
@@ -49,7 +76,7 @@ type CommandSwitchAccount struct {
Host v2net.Address
Port v2net.Port
ID *uuid.UUID
AlterIds serial.Uint16Literal
AlterIds uint16
Level UserLevel
ValidMin byte
}

View File

@@ -0,0 +1,34 @@
package protocol_test
import (
"testing"
. "github.com/v2ray/v2ray-core/common/protocol"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestRequestOptionSet(t *testing.T) {
assert := assert.On(t)
var option RequestOption
assert.Bool(option.Has(RequestOptionChunkStream)).IsFalse()
option.Set(RequestOptionChunkStream)
assert.Bool(option.Has(RequestOptionChunkStream)).IsTrue()
option.Set(RequestOptionConnectionReuse)
assert.Bool(option.Has(RequestOptionConnectionReuse)).IsTrue()
assert.Bool(option.Has(RequestOptionChunkStream)).IsTrue()
}
func TestRequestOptionClear(t *testing.T) {
assert := assert.On(t)
var option RequestOption
option.Set(RequestOptionChunkStream)
option.Set(RequestOptionConnectionReuse)
option.Clear(RequestOptionChunkStream)
assert.Bool(option.Has(RequestOptionChunkStream)).IsFalse()
assert.Bool(option.Has(RequestOptionConnectionReuse)).IsTrue()
}

View File

@@ -3,16 +3,15 @@ package protocol_test
import (
"testing"
"github.com/v2ray/v2ray-core/common/predicate"
. "github.com/v2ray/v2ray-core/common/protocol"
"github.com/v2ray/v2ray-core/common/serial"
"github.com/v2ray/v2ray-core/common/uuid"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestCmdKey(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
id := NewID(uuid.New())
assert.Bool(serial.BytesLiteral(id.CmdKey()).All(0)).IsFalse()
assert.Bool(predicate.BytesAll(id.CmdKey(), 0)).IsFalse()
}

View File

@@ -0,0 +1,90 @@
package protocol
import (
"sync"
)
type ServerList struct {
sync.RWMutex
servers []*ServerSpec
}
func NewServerList() *ServerList {
return &ServerList{}
}
func (this *ServerList) AddServer(server *ServerSpec) {
this.Lock()
defer this.Unlock()
this.servers = append(this.servers, server)
}
func (this *ServerList) Size() uint32 {
this.RLock()
defer this.RUnlock()
return uint32(len(this.servers))
}
func (this *ServerList) GetServer(idx uint32) *ServerSpec {
this.RLock()
defer this.RUnlock()
for {
if idx >= uint32(len(this.servers)) {
return nil
}
server := this.servers[idx]
if !server.IsValid() {
this.RemoveServer(idx)
continue
}
return server
}
}
// @Private
func (this *ServerList) RemoveServer(idx uint32) {
n := len(this.servers)
this.servers[idx] = this.servers[n-1]
this.servers = this.servers[:n-1]
}
type ServerPicker interface {
PickServer() *ServerSpec
}
type RoundRobinServerPicker struct {
sync.Mutex
serverlist *ServerList
nextIndex uint32
}
func NewRoundRobinServerPicker(serverlist *ServerList) *RoundRobinServerPicker {
return &RoundRobinServerPicker{
serverlist: serverlist,
nextIndex: 0,
}
}
func (this *RoundRobinServerPicker) PickServer() *ServerSpec {
this.Lock()
defer this.Unlock()
next := this.nextIndex
server := this.serverlist.GetServer(next)
if server == nil {
next = 0
server = this.serverlist.GetServer(0)
}
next++
if next >= this.serverlist.Size() {
next = 0
}
this.nextIndex = next
return server
}

View File

@@ -0,0 +1,54 @@
package protocol_test
import (
"testing"
"time"
v2net "github.com/v2ray/v2ray-core/common/net"
. "github.com/v2ray/v2ray-core/common/protocol"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestServerList(t *testing.T) {
assert := assert.On(t)
list := NewServerList()
list.AddServer(NewServerSpec(v2net.TCPDestination(v2net.LocalHostIP, v2net.Port(1)), AlwaysValid()))
assert.Uint32(list.Size()).Equals(1)
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)
assert.Port(server.Destination().Port()).Equals(2)
time.Sleep(2 * time.Second)
server = list.GetServer(1)
assert.Pointer(server).IsNil()
server = list.GetServer(0)
assert.Port(server.Destination().Port()).Equals(1)
}
func TestServerPicker(t *testing.T) {
assert := assert.On(t)
list := NewServerList()
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()
assert.Port(server.Destination().Port()).Equals(1)
server = picker.PickServer()
assert.Port(server.Destination().Port()).Equals(2)
server = picker.PickServer()
assert.Port(server.Destination().Port()).Equals(3)
server = picker.PickServer()
assert.Port(server.Destination().Port()).Equals(1)
time.Sleep(2 * time.Second)
server = picker.PickServer()
assert.Port(server.Destination().Port()).Equals(1)
server = picker.PickServer()
assert.Port(server.Destination().Port()).Equals(1)
}

View File

@@ -0,0 +1,100 @@
package protocol
import (
"sync"
"time"
"github.com/v2ray/v2ray-core/common/dice"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type ValidationStrategy interface {
IsValid() bool
Invalidate()
}
type AlwaysValidStrategy struct{}
func AlwaysValid() ValidationStrategy {
return AlwaysValidStrategy{}
}
func (this AlwaysValidStrategy) IsValid() bool {
return true
}
func (this AlwaysValidStrategy) Invalidate() {}
type TimeoutValidStrategy struct {
until time.Time
}
func BeforeTime(t time.Time) ValidationStrategy {
return &TimeoutValidStrategy{
until: t,
}
}
func (this *TimeoutValidStrategy) IsValid() bool {
return this.until.After(time.Now())
}
func (this *TimeoutValidStrategy) Invalidate() {
this.until = time.Time{}
}
type ServerSpec struct {
sync.RWMutex
dest v2net.Destination
users []*User
valid ValidationStrategy
}
func NewServerSpec(dest v2net.Destination, valid ValidationStrategy, users ...*User) *ServerSpec {
return &ServerSpec{
dest: dest,
users: users,
valid: valid,
}
}
func (this *ServerSpec) Destination() v2net.Destination {
return this.dest
}
func (this *ServerSpec) HasUser(user *User) bool {
this.RLock()
defer this.RUnlock()
account := user.Account
for _, u := range this.users {
if u.Account.Equals(account) {
return true
}
}
return false
}
func (this *ServerSpec) AddUser(user *User) {
if this.HasUser(user) {
return
}
this.Lock()
defer this.Unlock()
this.users = append(this.users, user)
}
func (this *ServerSpec) PickUser() *User {
userCount := len(this.users)
return this.users[dice.Roll(userCount)]
}
func (this *ServerSpec) IsValid() bool {
return this.valid.IsValid()
}
func (this *ServerSpec) Invalidate() {
this.valid.Invalidate()
}

View File

@@ -0,0 +1,62 @@
package protocol_test
import (
"testing"
"time"
v2net "github.com/v2ray/v2ray-core/common/net"
. "github.com/v2ray/v2ray-core/common/protocol"
"github.com/v2ray/v2ray-core/testing/assert"
)
type TestAccount struct {
id int
}
func (this *TestAccount) Equals(account Account) bool {
return account.(*TestAccount).id == this.id
}
func TestServerSpecUser(t *testing.T) {
assert := assert.On(t)
account := &TestAccount{
id: 0,
}
user := NewUser(UserLevel(0), "")
user.Account = account
rec := NewServerSpec(v2net.TCPDestination(v2net.DomainAddress("v2ray.com"), 80), AlwaysValid(), user)
assert.Bool(rec.HasUser(user)).IsTrue()
account2 := &TestAccount{
id: 1,
}
user2 := NewUser(UserLevel(0), "")
user2.Account = account2
assert.Bool(rec.HasUser(user2)).IsFalse()
rec.AddUser(user2)
assert.Bool(rec.HasUser(user2)).IsTrue()
}
func TestAlwaysValidStrategy(t *testing.T) {
assert := assert.On(t)
strategy := AlwaysValid()
assert.Bool(strategy.IsValid()).IsTrue()
strategy.Invalidate()
assert.Bool(strategy.IsValid()).IsTrue()
}
func TestTimeoutValidStrategy(t *testing.T) {
assert := assert.On(t)
strategy := BeforeTime(time.Now().Add(2 * time.Second))
assert.Bool(strategy.IsValid()).IsTrue()
time.Sleep(3 * time.Second)
assert.Bool(strategy.IsValid()).IsFalse()
strategy = BeforeTime(time.Now().Add(2 * time.Second))
strategy.Invalidate()
assert.Bool(strategy.IsValid()).IsFalse()
}

View File

@@ -1,16 +1,16 @@
package protocol
import (
"math/rand"
"time"
"github.com/v2ray/v2ray-core/common/dice"
"github.com/v2ray/v2ray-core/common/serial"
)
type Timestamp int64
func (this Timestamp) Bytes() []byte {
return serial.Int64Literal(this).Bytes()
func (this Timestamp) Bytes(b []byte) []byte {
return serial.Int64ToBytes(int64(this), b)
}
type TimestampGenerator func() Timestamp
@@ -21,7 +21,7 @@ func NowTime() Timestamp {
func NewTimestampGenerator(base Timestamp, delta int) TimestampGenerator {
return func() Timestamp {
rangeInDelta := rand.Intn(delta*2) - delta
rangeInDelta := dice.Roll(delta*2) - delta
return base + Timestamp(rangeInDelta)
}
}

View File

@@ -5,12 +5,11 @@ import (
"time"
. "github.com/v2ray/v2ray-core/common/protocol"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestGenerateRandomInt64InRange(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
base := time.Now().Unix()
delta := 100

View File

@@ -1,9 +1,5 @@
package protocol
import (
"github.com/v2ray/v2ray-core/common/dice"
)
type UserLevel byte
const (
@@ -12,28 +8,18 @@ const (
)
type User struct {
ID *ID
AlterIDs []*ID
Level UserLevel
Email string
Account Account
Level UserLevel
Email string
}
func NewUser(primary *ID, secondary []*ID, level UserLevel, email string) *User {
func NewUser(level UserLevel, email string) *User {
return &User{
ID: primary,
AlterIDs: secondary,
Level: level,
Email: email,
Level: level,
Email: email,
}
}
func (this *User) AnyValidID() *ID {
if len(this.AlterIDs) == 0 {
return this.ID
}
return this.AlterIDs[dice.Roll(len(this.AlterIDs))]
}
type UserSettings struct {
PayloadReadTimeout int
}

View File

@@ -2,30 +2,20 @@
package protocol
import (
"encoding/json"
"github.com/v2ray/v2ray-core/common/uuid"
)
import "encoding/json"
func (u *User) UnmarshalJSON(data []byte) error {
type rawUser struct {
IdString string `json:"id"`
EmailString string `json:"email"`
LevelByte byte `json:"level"`
AlterIdCount uint16 `json:"alterId"`
EmailString string `json:"email"`
LevelByte byte `json:"level"`
}
var rawUserValue rawUser
if err := json.Unmarshal(data, &rawUserValue); err != nil {
return err
}
id, err := uuid.ParseString(rawUserValue.IdString)
if err != nil {
return err
}
primaryID := NewID(id)
alterIDs := NewAlterIDs(primaryID, rawUserValue.AlterIdCount)
*u = *NewUser(primaryID, alterIDs, UserLevel(rawUserValue.LevelByte), rawUserValue.EmailString)
u.Email = rawUserValue.EmailString
u.Level = UserLevel(rawUserValue.LevelByte)
return nil
}

View File

@@ -7,12 +7,11 @@ import (
"testing"
. "github.com/v2ray/v2ray-core/common/protocol"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestUserParsing(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{
@@ -22,22 +21,14 @@ func TestUserParsing(t *testing.T) {
"alterId": 100
}`), user)
assert.Error(err).IsNil()
assert.String(user.ID).Equals("96edb838-6d68-42ef-a933-25f7ac3a9d09")
assert.Byte(byte(user.Level)).Equals(1)
assert.String(user.Email).Equals("love@v2ray.com")
}
func TestInvalidUserJson(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
user := new(User)
err := json.Unmarshal([]byte(`{"id": 1234}`), user)
assert.Error(err).IsNotNil()
}
func TestInvalidIdJson(t *testing.T) {
v2testing.Current(t)
user := new(User)
err := json.Unmarshal([]byte(`{"id": "1234"}`), user)
err := json.Unmarshal([]byte(`{"email": 1234}`), user)
assert.Error(err).IsNotNil()
}

View File

@@ -1,145 +1,12 @@
package protocol
import (
"sync"
"time"
"github.com/v2ray/v2ray-core/common"
"github.com/v2ray/v2ray-core/common/signal"
)
const (
updateIntervalSec = 10
cacheDurationSec = 120
)
type idEntry struct {
id *ID
userIdx int
lastSec Timestamp
lastSecRemoval Timestamp
}
type UserValidator interface {
common.Releasable
Add(user *User) error
Get(timeHash []byte) (*User, Timestamp, bool)
}
type TimedUserValidator struct {
validUsers []*User
userHash map[[16]byte]*indexTimePair
ids []*idEntry
access sync.RWMutex
hasher IDHash
cancel *signal.CancelSignal
}
type indexTimePair struct {
index int
timeSec Timestamp
}
func NewTimedUserValidator(hasher IDHash) UserValidator {
tus := &TimedUserValidator{
validUsers: make([]*User, 0, 16),
userHash: make(map[[16]byte]*indexTimePair, 512),
access: sync.RWMutex{},
ids: make([]*idEntry, 0, 512),
hasher: hasher,
cancel: signal.NewCloseSignal(),
}
go tus.updateUserHash(time.Tick(updateIntervalSec*time.Second), tus.cancel)
return tus
}
func (this *TimedUserValidator) Release() {
this.cancel.Cancel()
<-this.cancel.WaitForDone()
this.validUsers = nil
this.userHash = nil
this.ids = nil
this.hasher = nil
this.cancel = nil
}
func (this *TimedUserValidator) generateNewHashes(nowSec Timestamp, idx int, entry *idEntry) {
var hashValue [16]byte
var hashValueRemoval [16]byte
idHash := this.hasher(entry.id.Bytes())
for entry.lastSec <= nowSec {
idHash.Write(entry.lastSec.Bytes())
idHash.Sum(hashValue[:0])
idHash.Reset()
idHash.Write(entry.lastSecRemoval.Bytes())
idHash.Sum(hashValueRemoval[:0])
idHash.Reset()
this.access.Lock()
this.userHash[hashValue] = &indexTimePair{idx, entry.lastSec}
delete(this.userHash, hashValueRemoval)
this.access.Unlock()
entry.lastSec++
entry.lastSecRemoval++
}
}
func (this *TimedUserValidator) updateUserHash(tick <-chan time.Time, cancel *signal.CancelSignal) {
L:
for {
select {
case now := <-tick:
nowSec := Timestamp(now.Unix() + cacheDurationSec)
for _, entry := range this.ids {
this.generateNewHashes(nowSec, entry.userIdx, entry)
}
case <-cancel.WaitForCancel():
break L
}
}
cancel.Done()
}
func (this *TimedUserValidator) Add(user *User) error {
idx := len(this.validUsers)
this.validUsers = append(this.validUsers, user)
nowSec := time.Now().Unix()
entry := &idEntry{
id: user.ID,
userIdx: idx,
lastSec: Timestamp(nowSec - cacheDurationSec),
lastSecRemoval: Timestamp(nowSec - cacheDurationSec*3),
}
this.generateNewHashes(Timestamp(nowSec+cacheDurationSec), idx, entry)
this.ids = append(this.ids, entry)
for _, alterid := range user.AlterIDs {
entry := &idEntry{
id: alterid,
userIdx: idx,
lastSec: Timestamp(nowSec - cacheDurationSec),
lastSecRemoval: Timestamp(nowSec - cacheDurationSec*3),
}
this.generateNewHashes(Timestamp(nowSec+cacheDurationSec), idx, entry)
this.ids = append(this.ids, entry)
}
return nil
}
func (this *TimedUserValidator) Get(userHash []byte) (*User, Timestamp, bool) {
defer this.access.RUnlock()
this.access.RLock()
var fixedSizeHash [16]byte
copy(fixedSizeHash[:], userHash)
pair, found := this.userHash[fixedSizeHash]
if found {
return this.validUsers[pair.index], pair.timeSec, true
}
return nil, 0, false
}

View File

@@ -6,7 +6,7 @@ import (
)
var (
ErrorRetryFailed = errors.New("All retry attempts failed.")
ErrRetryFailed = errors.New("All retry attempts failed.")
)
// Strategy is a way to retry on a specific function.
@@ -29,7 +29,7 @@ func (r *retryer) On(method func() error) error {
}
delay := r.NextDelay(attempt)
if delay < 0 {
return ErrorRetryFailed
return ErrRetryFailed
}
<-time.After(time.Duration(delay) * time.Millisecond)
attempt++

View File

@@ -6,7 +6,6 @@ import (
"time"
. "github.com/v2ray/v2ray-core/common/retry"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
@@ -15,7 +14,7 @@ var (
)
func TestNoRetry(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
startTime := time.Now().Unix()
err := Timed(10, 100000).On(func() error {
@@ -28,7 +27,7 @@ func TestNoRetry(t *testing.T) {
}
func TestRetryOnce(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
startTime := time.Now()
called := 0
@@ -46,7 +45,7 @@ func TestRetryOnce(t *testing.T) {
}
func TestRetryMultiple(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
startTime := time.Now()
called := 0
@@ -64,7 +63,7 @@ func TestRetryMultiple(t *testing.T) {
}
func TestRetryExhausted(t *testing.T) {
v2testing.Current(t)
assert := assert.On(t)
startTime := time.Now()
called := 0
@@ -77,6 +76,6 @@ func TestRetryExhausted(t *testing.T) {
})
duration := time.Since(startTime)
assert.Error(err).Equals(ErrorRetryFailed)
assert.Error(err).Equals(ErrRetryFailed)
assert.Int64(int64(duration / time.Millisecond)).AtLeast(1900)
}

View File

@@ -1,72 +1,40 @@
package serial
import (
"bytes"
"encoding/hex"
"strings"
)
type Bytes interface {
Bytes() []byte
func ByteToHexString(value byte) string {
return hex.EncodeToString([]byte{value})
}
type BytesLiteral []byte
func (this BytesLiteral) Value() []byte {
return []byte(this)
func BytesToUint16(value []byte) uint16 {
return uint16(value[0])<<8 | uint16(value[1])
}
func (this BytesLiteral) Equals(another BytesLiteral) bool {
return bytes.Equal(this.Value(), another.Value())
}
func (this BytesLiteral) Uint8Value() uint8 {
return this.Value()[0]
}
func (this BytesLiteral) Uint16() Uint16Literal {
return Uint16Literal(this.Uint16Value())
}
func (this BytesLiteral) Uint16Value() uint16 {
value := this.Value()
return uint16(value[0])<<8 + uint16(value[1])
}
func (this BytesLiteral) IntValue() int {
value := this.Value()
return int(value[0])<<24 + int(value[1])<<16 + int(value[2])<<8 + int(value[3])
}
func (this BytesLiteral) Uint32Value() uint32 {
value := this.Value()
return uint32(value[0])<<24 +
uint32(value[1])<<16 +
uint32(value[2])<<8 +
func BytesToUint32(value []byte) uint32 {
return uint32(value[0])<<24 |
uint32(value[1])<<16 |
uint32(value[2])<<8 |
uint32(value[3])
}
func (this BytesLiteral) Int64Value() int64 {
value := this.Value()
return int64(value[0])<<56 +
int64(value[1])<<48 +
int64(value[2])<<40 +
int64(value[3])<<32 +
int64(value[4])<<24 +
int64(value[5])<<16 +
int64(value[6])<<8 +
func BytesToInt64(value []byte) int64 {
return int64(value[0])<<56 |
int64(value[1])<<48 |
int64(value[2])<<40 |
int64(value[3])<<32 |
int64(value[4])<<24 |
int64(value[5])<<16 |
int64(value[6])<<8 |
int64(value[7])
}
// String returns a string presentation of this ByteLiteral
func (this BytesLiteral) String() string {
return string(this.Value())
}
// All returns true if all bytes in the ByteLiteral are the same as given value.
func (this BytesLiteral) All(v byte) bool {
for _, b := range this {
if b != v {
return false
}
func BytesToHexString(value []byte) string {
strs := make([]string, len(value))
for i, b := range value {
strs[i] = hex.EncodeToString([]byte{b})
}
return true
return "[" + strings.Join(strs, ",") + "]"
}

View File

@@ -0,0 +1,9 @@
package serial
import (
"fmt"
)
func PointerToString(value interface{}) string {
return fmt.Sprint(value)
}

View File

@@ -4,68 +4,42 @@ import (
"strconv"
)
type Uint16 interface {
Value() uint16
func Uint16ToBytes(value uint16, b []byte) []byte {
return append(b, byte(value>>8), byte(value))
}
type Uint16Literal uint16
func (this Uint16Literal) String() string {
return strconv.Itoa(int(this))
func Uint16ToString(value uint16) string {
return strconv.Itoa(int(value))
}
func (this Uint16Literal) Value() uint16 {
return uint16(this)
func Uint32ToBytes(value uint32, b []byte) []byte {
return append(b, byte(value>>24), byte(value>>16), byte(value>>8), byte(value))
}
func (this Uint16Literal) Bytes() []byte {
return []byte{byte(this >> 8), byte(this)}
func Uint32ToString(value uint32) string {
return strconv.FormatUint(uint64(value), 10)
}
type Int interface {
Value() int
func IntToBytes(value int, b []byte) []byte {
return append(b, byte(value>>24), byte(value>>16), byte(value>>8), byte(value))
}
type IntLiteral int
func (this IntLiteral) String() string {
return strconv.Itoa(int(this))
func IntToString(value int) string {
return Int64ToString(int64(value))
}
func (this IntLiteral) Value() int {
return int(this)
func Int64ToBytes(value int64, b []byte) []byte {
return append(b,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value))
}
func (this IntLiteral) Bytes() []byte {
value := this.Value()
return []byte{
byte(value >> 24),
byte(value >> 16),
byte(value >> 8),
byte(value),
}
}
type Int64Literal int64
func (this Int64Literal) String() string {
return strconv.FormatInt(this.Value(), 10)
}
func (this Int64Literal) Value() int64 {
return int64(this)
}
func (this Int64Literal) Bytes() []byte {
value := this.Value()
return []byte{
byte(value >> 56),
byte(value >> 48),
byte(value >> 40),
byte(value >> 32),
byte(value >> 24),
byte(value >> 16),
byte(value >> 8),
byte(value),
}
func Int64ToString(value int64) string {
return strconv.FormatInt(value, 10)
}

View File

@@ -1,36 +0,0 @@
package serial
import (
"strings"
)
// An interface for any objects that has string presentation.
type String interface {
String() string
}
type StringLiteral string
func NewStringLiteral(str String) StringLiteral {
return StringLiteral(str.String())
}
func (this StringLiteral) Contains(str String) bool {
return strings.Contains(this.String(), str.String())
}
func (this StringLiteral) String() string {
return string(this)
}
func (this StringLiteral) ToLower() StringLiteral {
return StringLiteral(strings.ToLower(string(this)))
}
func (this StringLiteral) ToUpper() StringLiteral {
return StringLiteral(strings.ToUpper(string(this)))
}
func (this StringLiteral) TrimSpace() StringLiteral {
return StringLiteral(strings.TrimSpace(string(this)))
}

View File

@@ -1,16 +0,0 @@
// +build json
package serial
import (
"encoding/json"
)
func (this *StringLiteral) UnmarshalJSON(data []byte) error {
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
*this = StringLiteral(str)
return nil
}

View File

@@ -1,29 +0,0 @@
// +build json
package serial_test
import (
"encoding/json"
"testing"
. "github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
func TestInvalidStringLiteralJson(t *testing.T) {
v2testing.Current(t)
var s StringLiteral
err := json.Unmarshal([]byte("1"), &s)
assert.Error(err).IsNotNil()
}
func TestStringLiteralParsing(t *testing.T) {
v2testing.Current(t)
var s StringLiteral
err := json.Unmarshal([]byte("\"1\""), &s)
assert.Error(err).IsNil()
assert.String(s).Equals("1")
}

View File

@@ -1,15 +0,0 @@
package serial
type StringLiteralList []StringLiteral
func NewStringLiteralList(raw []string) *StringLiteralList {
list := StringLiteralList(make([]StringLiteral, len(raw)))
for idx, str := range raw {
list[idx] = StringLiteral(str)
}
return &list
}
func (this *StringLiteralList) Len() int {
return len(*this)
}

View File

@@ -1,24 +0,0 @@
package serial_test
import (
"testing"
. "github.com/v2ray/v2ray-core/common/serial"
v2testing "github.com/v2ray/v2ray-core/testing"
"github.com/v2ray/v2ray-core/testing/assert"
)
type TestString struct {
value string
}
func (this *TestString) String() string {
return this.value
}
func TestNewStringSerial(t *testing.T) {
v2testing.Current(t)
testString := &TestString{value: "abcd"}
assert.String(NewStringLiteral(testString)).Equals("abcd")
}

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