use yamux as go-peerstream transport
go-peerstream update to use github.com/hashicorp/yamux
Juan Batiz-Benet committed
Jan 1, 2015 at 23:24 UTC
8acfcebd67effb6ee31432f96bd70aef1e4b85ca
39 files changed
+2895
-4211
Godeps/Godeps.json
+5
-10
@@ -34,11 +34,6 @@
34
"Comment": "null-144",
35
"Rev": "ad01a6fcc8a19d3a4478c836895ffe883bd2ceab"
36
},
37
- {
38
- "ImportPath": "code.google.com/p/go.net/spdy",
39
- "Comment": "null-144",
40
- "Rev": "ad01a6fcc8a19d3a4478c836895ffe883bd2ceab"
41
- },
37
{
38
"ImportPath": "code.google.com/p/gogoprotobuf/io",
39
"Rev": "6c980277330804e94257ac7ef70a3adbe1641059"
@@ -93,6 +88,10 @@
88
"ImportPath": "github.com/hashicorp/golang-lru",
89
"Rev": "253b2dc1ca8bae42c3b5b6e53dd2eab1a7551116"
90
},
91
+ {
92
+ "ImportPath": "github.com/hashicorp/yamux",
93
+ "Rev": "9feabe6854fadca1abec9cd3bd2a613fe9a34000"
94
+ },
95
{
96
"ImportPath": "github.com/inconshreveable/go-update",
97
"Rev": "221d034a558b4c21b0624b2a450c076913854a57"
@@ -137,16 +136,12 @@
136
},
137
{
138
"ImportPath": "github.com/jbenet/go-peerstream",
140
- "Rev": "3f8972989ecf7b99db5d718b7ff2e1bf31011d4f"
139
+ "Rev": "eab3056e47ecbd1bb32b8c8512fe46fc856f0387"
140
},
141
{
142
"ImportPath": "github.com/jbenet/go-random",
143
"Rev": "2e83344e7dc7898f94501665af34edd4aa95a013"
144
},
146
- {
147
- "ImportPath": "github.com/jbenet/spdystream",
148
- "Rev": "6daa2792a4c92f14c76b2b1caa99a76824f7705c"
149
- },
145
{
146
"ImportPath": "github.com/kr/binarydist",
147
"Rev": "9955b0ab8708602d411341e55fffd7e0700f86bd"
Godeps/_workspace/src/code.google.com/p/go.net/spdy/dictionary.go
deleted
-187
@@ -1,187 +0,0 @@
1
-// Copyright 2013 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-package spdy
6
-
7
-// headerDictionary is the dictionary sent to the zlib compressor/decompressor.
8
-var headerDictionary = []byte{
9
- 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69,
10
- 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68,
11
- 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70,
12
- 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70,
13
- 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65,
14
- 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05,
15
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00,
16
- 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00,
17
- 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70,
18
- 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
19
- 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63,
20
- 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,
21
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f,
22
- 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c,
23
- 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00,
24
- 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70,
25
- 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73,
26
- 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00,
27
- 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77,
28
- 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68,
29
- 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
30
- 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63,
31
- 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,
32
- 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f,
33
- 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
34
- 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74,
35
- 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65,
36
- 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74,
37
- 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f,
38
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10,
39
- 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
40
- 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,
41
- 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
42
- 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67,
43
- 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f,
44
- 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f,
45
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
46
- 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
47
- 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00,
48
- 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
49
- 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00,
50
- 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
51
- 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00,
52
- 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00,
53
- 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00,
54
- 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
55
- 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69,
56
- 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66,
57
- 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68,
58
- 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69,
59
- 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00,
60
- 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f,
61
- 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73,
62
- 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d,
63
- 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d,
64
- 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00,
65
- 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67,
66
- 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d,
67
- 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
68
- 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65,
69
- 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74,
70
- 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,
71
- 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63,
72
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00,
73
- 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72,
74
- 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00,
75
- 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00,
76
- 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79,
77
- 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74,
78
- 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00,
79
- 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61,
80
- 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61,
81
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05,
82
- 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00,
83
- 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72,
84
- 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72,
85
- 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00,
86
- 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
87
- 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00,
88
- 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c,
89
- 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72,
90
- 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65,
91
- 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00,
92
- 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61,
93
- 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73,
94
- 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74,
95
- 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79,
96
- 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00,
97
- 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69,
98
- 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77,
99
- 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e,
100
- 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00,
101
- 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
102
- 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00,
103
- 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
104
- 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30,
105
- 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76,
106
- 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00,
107
- 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31,
108
- 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72,
109
- 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62,
110
- 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73,
111
- 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69,
112
- 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65,
113
- 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00,
114
- 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69,
115
- 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32,
116
- 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35,
117
- 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30,
118
- 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33,
119
- 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37,
120
- 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30,
121
- 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34,
122
- 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31,
123
- 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31,
124
- 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34,
125
- 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34,
126
- 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e,
127
- 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f,
128
- 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65,
129
- 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,
130
- 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20,
131
- 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65,
132
- 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f,
133
- 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d,
134
- 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34,
135
- 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52,
136
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30,
137
- 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68,
138
- 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30,
139
- 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64,
140
- 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e,
141
- 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64,
142
- 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65,
143
- 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72,
144
- 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f,
145
- 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74,
146
- 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65,
147
- 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20,
148
- 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20,
149
- 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61,
150
- 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46,
151
- 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41,
152
- 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a,
153
- 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41,
154
- 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20,
155
- 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20,
156
- 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30,
157
- 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e,
158
- 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57,
159
- 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c,
160
- 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61,
161
- 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20,
162
- 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b,
163
- 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f,
164
- 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61,
165
- 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69,
166
- 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67,
167
- 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67,
168
- 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,
169
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,
170
- 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69,
171
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78,
172
- 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c,
173
- 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c,
174
- 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74,
175
- 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72,
176
- 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c,
177
- 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74,
178
- 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65,
179
- 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65,
180
- 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64,
181
- 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,
182
- 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,
183
- 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,
184
- 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,
185
- 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,
186
- 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e,
187
-}
Godeps/_workspace/src/code.google.com/p/go.net/spdy/read.go
deleted
-348
@@ -1,348 +0,0 @@
1
-// Copyright 2011 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-package spdy
6
-
7
-import (
8
- "compress/zlib"
9
- "encoding/binary"
10
- "io"
11
- "net/http"
12
- "strings"
13
-)
14
-
15
-func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
16
- return f.readSynStreamFrame(h, frame)
17
-}
18
-
19
-func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
20
- return f.readSynReplyFrame(h, frame)
21
-}
22
-
23
-func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
24
- frame.CFHeader = h
25
- if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
26
- return err
27
- }
28
- if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
29
- return err
30
- }
31
- if frame.Status == 0 {
32
- return &Error{InvalidControlFrame, frame.StreamId}
33
- }
34
- if frame.StreamId == 0 {
35
- return &Error{ZeroStreamId, 0}
36
- }
37
- return nil
38
-}
39
-
40
-func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
41
- frame.CFHeader = h
42
- var numSettings uint32
43
- if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
44
- return err
45
- }
46
- frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
47
- for i := uint32(0); i < numSettings; i++ {
48
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
49
- return err
50
- }
51
- frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
52
- frame.FlagIdValues[i].Id &= 0xffffff
53
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
54
- return err
55
- }
56
- }
57
- return nil
58
-}
59
-
60
-func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
61
- frame.CFHeader = h
62
- if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
63
- return err
64
- }
65
- if frame.Id == 0 {
66
- return &Error{ZeroStreamId, 0}
67
- }
68
- if frame.CFHeader.Flags != 0 {
69
- return &Error{InvalidControlFrame, StreamId(frame.Id)}
70
- }
71
- return nil
72
-}
73
-
74
-func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
75
- frame.CFHeader = h
76
- if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
77
- return err
78
- }
79
- if frame.CFHeader.Flags != 0 {
80
- return &Error{InvalidControlFrame, frame.LastGoodStreamId}
81
- }
82
- if frame.CFHeader.length != 8 {
83
- return &Error{InvalidControlFrame, frame.LastGoodStreamId}
84
- }
85
- if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
86
- return err
87
- }
88
- return nil
89
-}
90
-
91
-func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
92
- return f.readHeadersFrame(h, frame)
93
-}
94
-
95
-func (frame *WindowUpdateFrame) read(h ControlFrameHeader, f *Framer) error {
96
- frame.CFHeader = h
97
- if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
98
- return err
99
- }
100
- if frame.CFHeader.Flags != 0 {
101
- return &Error{InvalidControlFrame, frame.StreamId}
102
- }
103
- if frame.CFHeader.length != 8 {
104
- return &Error{InvalidControlFrame, frame.StreamId}
105
- }
106
- if err := binary.Read(f.r, binary.BigEndian, &frame.DeltaWindowSize); err != nil {
107
- return err
108
- }
109
- return nil
110
-}
111
-
112
-func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
113
- ctor, ok := cframeCtor[frameType]
114
- if !ok {
115
- return nil, &Error{Err: InvalidControlFrame}
116
- }
117
- return ctor(), nil
118
-}
119
-
120
-var cframeCtor = map[ControlFrameType]func() controlFrame{
121
- TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
122
- TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
123
- TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
124
- TypeSettings: func() controlFrame { return new(SettingsFrame) },
125
- TypePing: func() controlFrame { return new(PingFrame) },
126
- TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
127
- TypeHeaders: func() controlFrame { return new(HeadersFrame) },
128
- TypeWindowUpdate: func() controlFrame { return new(WindowUpdateFrame) },
129
-}
130
-
131
-func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
132
- if f.headerDecompressor != nil {
133
- f.headerReader.N = payloadSize
134
- return nil
135
- }
136
- f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
137
- decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(headerDictionary))
138
- if err != nil {
139
- return err
140
- }
141
- f.headerDecompressor = decompressor
142
- return nil
143
-}
144
-
145
-// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
146
-func (f *Framer) ReadFrame() (Frame, error) {
147
- var firstWord uint32
148
- if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
149
- return nil, err
150
- }
151
- if firstWord&0x80000000 != 0 {
152
- frameType := ControlFrameType(firstWord & 0xffff)
153
- version := uint16(firstWord >> 16 & 0x7fff)
154
- return f.parseControlFrame(version, frameType)
155
- }
156
- return f.parseDataFrame(StreamId(firstWord & 0x7fffffff))
157
-}
158
-
159
-func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
160
- var length uint32
161
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
162
- return nil, err
163
- }
164
- flags := ControlFlags((length & 0xff000000) >> 24)
165
- length &= 0xffffff
166
- header := ControlFrameHeader{version, frameType, flags, length}
167
- cframe, err := newControlFrame(frameType)
168
- if err != nil {
169
- return nil, err
170
- }
171
- if err = cframe.read(header, f); err != nil {
172
- return nil, err
173
- }
174
- return cframe, nil
175
-}
176
-
177
-func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
178
- var numHeaders uint32
179
- if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
180
- return nil, err
181
- }
182
- var e error
183
- h := make(http.Header, int(numHeaders))
184
- for i := 0; i < int(numHeaders); i++ {
185
- var length uint32
186
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
187
- return nil, err
188
- }
189
- nameBytes := make([]byte, length)
190
- if _, err := io.ReadFull(r, nameBytes); err != nil {
191
- return nil, err
192
- }
193
- name := string(nameBytes)
194
- if name != strings.ToLower(name) {
195
- e = &Error{UnlowercasedHeaderName, streamId}
196
- name = strings.ToLower(name)
197
- }
198
- if h[name] != nil {
199
- e = &Error{DuplicateHeaders, streamId}
200
- }
201
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
202
- return nil, err
203
- }
204
- value := make([]byte, length)
205
- if _, err := io.ReadFull(r, value); err != nil {
206
- return nil, err
207
- }
208
- valueList := strings.Split(string(value), headerValueSeparator)
209
- for _, v := range valueList {
210
- h.Add(name, v)
211
- }
212
- }
213
- if e != nil {
214
- return h, e
215
- }
216
- return h, nil
217
-}
218
-
219
-func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
220
- frame.CFHeader = h
221
- var err error
222
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
223
- return err
224
- }
225
- if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
226
- return err
227
- }
228
- if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
229
- return err
230
- }
231
- frame.Priority >>= 5
232
- if err = binary.Read(f.r, binary.BigEndian, &frame.Slot); err != nil {
233
- return err
234
- }
235
- reader := f.r
236
- if !f.headerCompressionDisabled {
237
- err := f.uncorkHeaderDecompressor(int64(h.length - 10))
238
- if err != nil {
239
- return err
240
- }
241
- reader = f.headerDecompressor
242
- }
243
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
244
- if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
245
- err = &Error{WrongCompressedPayloadSize, 0}
246
- }
247
- if err != nil {
248
- return err
249
- }
250
- for h := range frame.Headers {
251
- if invalidReqHeaders[h] {
252
- return &Error{InvalidHeaderPresent, frame.StreamId}
253
- }
254
- }
255
- if frame.StreamId == 0 {
256
- return &Error{ZeroStreamId, 0}
257
- }
258
- return nil
259
-}
260
-
261
-func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
262
- frame.CFHeader = h
263
- var err error
264
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
265
- return err
266
- }
267
- reader := f.r
268
- if !f.headerCompressionDisabled {
269
- err := f.uncorkHeaderDecompressor(int64(h.length - 4))
270
- if err != nil {
271
- return err
272
- }
273
- reader = f.headerDecompressor
274
- }
275
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
276
- if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
277
- err = &Error{WrongCompressedPayloadSize, 0}
278
- }
279
- if err != nil {
280
- return err
281
- }
282
- for h := range frame.Headers {
283
- if invalidRespHeaders[h] {
284
- return &Error{InvalidHeaderPresent, frame.StreamId}
285
- }
286
- }
287
- if frame.StreamId == 0 {
288
- return &Error{ZeroStreamId, 0}
289
- }
290
- return nil
291
-}
292
-
293
-func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
294
- frame.CFHeader = h
295
- var err error
296
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
297
- return err
298
- }
299
- reader := f.r
300
- if !f.headerCompressionDisabled {
301
- err := f.uncorkHeaderDecompressor(int64(h.length - 4))
302
- if err != nil {
303
- return err
304
- }
305
- reader = f.headerDecompressor
306
- }
307
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
308
- if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
309
- err = &Error{WrongCompressedPayloadSize, 0}
310
- }
311
- if err != nil {
312
- return err
313
- }
314
- var invalidHeaders map[string]bool
315
- if frame.StreamId%2 == 0 {
316
- invalidHeaders = invalidReqHeaders
317
- } else {
318
- invalidHeaders = invalidRespHeaders
319
- }
320
- for h := range frame.Headers {
321
- if invalidHeaders[h] {
322
- return &Error{InvalidHeaderPresent, frame.StreamId}
323
- }
324
- }
325
- if frame.StreamId == 0 {
326
- return &Error{ZeroStreamId, 0}
327
- }
328
- return nil
329
-}
330
-
331
-func (f *Framer) parseDataFrame(streamId StreamId) (*DataFrame, error) {
332
- var length uint32
333
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
334
- return nil, err
335
- }
336
- var frame DataFrame
337
- frame.StreamId = streamId
338
- frame.Flags = DataFlags(length >> 24)
339
- length &= 0xffffff
340
- frame.Data = make([]byte, length)
341
- if _, err := io.ReadFull(f.r, frame.Data); err != nil {
342
- return nil, err
343
- }
344
- if frame.StreamId == 0 {
345
- return nil, &Error{ZeroStreamId, 0}
346
- }
347
- return &frame, nil
348
-}
Godeps/_workspace/src/code.google.com/p/go.net/spdy/spdy_test.go
deleted
-644
@@ -1,644 +0,0 @@
1
-// Copyright 2011 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-package spdy
6
-
7
-import (
8
- "bytes"
9
- "compress/zlib"
10
- "encoding/base64"
11
- "io"
12
- "io/ioutil"
13
- "net/http"
14
- "reflect"
15
- "testing"
16
-)
17
-
18
-var HeadersFixture = http.Header{
19
- "Url": []string{"http://www.google.com/"},
20
- "Method": []string{"get"},
21
- "Version": []string{"http/1.1"},
22
-}
23
-
24
-func TestHeaderParsing(t *testing.T) {
25
- var headerValueBlockBuf bytes.Buffer
26
- writeHeaderValueBlock(&headerValueBlockBuf, HeadersFixture)
27
- const bogusStreamId = 1
28
- newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
29
- if err != nil {
30
- t.Fatal("parseHeaderValueBlock:", err)
31
- }
32
- if !reflect.DeepEqual(HeadersFixture, newHeaders) {
33
- t.Fatal("got: ", newHeaders, "\nwant: ", HeadersFixture)
34
- }
35
-}
36
-
37
-func TestCreateParseSynStreamFrameCompressionDisable(t *testing.T) {
38
- buffer := new(bytes.Buffer)
39
- // Fixture framer for no compression test.
40
- framer := &Framer{
41
- headerCompressionDisabled: true,
42
- w: buffer,
43
- headerBuf: new(bytes.Buffer),
44
- r: buffer,
45
- }
46
- synStreamFrame := SynStreamFrame{
47
- CFHeader: ControlFrameHeader{
48
- version: Version,
49
- frameType: TypeSynStream,
50
- },
51
- StreamId: 2,
52
- Headers: HeadersFixture,
53
- }
54
- if err := framer.WriteFrame(&synStreamFrame); err != nil {
55
- t.Fatal("WriteFrame without compression:", err)
56
- }
57
- frame, err := framer.ReadFrame()
58
- if err != nil {
59
- t.Fatal("ReadFrame without compression:", err)
60
- }
61
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
62
- if !ok {
63
- t.Fatal("Parsed incorrect frame type:", frame)
64
- }
65
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
66
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
67
- }
68
-}
69
-
70
-func TestCreateParseSynStreamFrameCompressionEnable(t *testing.T) {
71
- buffer := new(bytes.Buffer)
72
- framer, err := NewFramer(buffer, buffer)
73
- synStreamFrame := SynStreamFrame{
74
- CFHeader: ControlFrameHeader{
75
- version: Version,
76
- frameType: TypeSynStream,
77
- },
78
- StreamId: 2,
79
- Headers: HeadersFixture,
80
- }
81
- if err != nil {
82
- t.Fatal("Failed to create new framer:", err)
83
- }
84
- if err := framer.WriteFrame(&synStreamFrame); err != nil {
85
- t.Fatal("WriteFrame with compression:", err)
86
- }
87
- frame, err := framer.ReadFrame()
88
- if err != nil {
89
- t.Fatal("ReadFrame with compression:", err)
90
- }
91
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
92
- if !ok {
93
- t.Fatal("Parsed incorrect frame type:", frame)
94
- }
95
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
96
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
97
- }
98
-}
99
-
100
-func TestCreateParseSynReplyFrameCompressionDisable(t *testing.T) {
101
- buffer := new(bytes.Buffer)
102
- framer := &Framer{
103
- headerCompressionDisabled: true,
104
- w: buffer,
105
- headerBuf: new(bytes.Buffer),
106
- r: buffer,
107
- }
108
- synReplyFrame := SynReplyFrame{
109
- CFHeader: ControlFrameHeader{
110
- version: Version,
111
- frameType: TypeSynReply,
112
- },
113
- StreamId: 2,
114
- Headers: HeadersFixture,
115
- }
116
- if err := framer.WriteFrame(&synReplyFrame); err != nil {
117
- t.Fatal("WriteFrame without compression:", err)
118
- }
119
- frame, err := framer.ReadFrame()
120
- if err != nil {
121
- t.Fatal("ReadFrame without compression:", err)
122
- }
123
- parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
124
- if !ok {
125
- t.Fatal("Parsed incorrect frame type:", frame)
126
- }
127
- if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
128
- t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
129
- }
130
-}
131
-
132
-func TestCreateParseSynReplyFrameCompressionEnable(t *testing.T) {
133
- buffer := new(bytes.Buffer)
134
- framer, err := NewFramer(buffer, buffer)
135
- synReplyFrame := SynReplyFrame{
136
- CFHeader: ControlFrameHeader{
137
- version: Version,
138
- frameType: TypeSynReply,
139
- },
140
- StreamId: 2,
141
- Headers: HeadersFixture,
142
- }
143
- if err != nil {
144
- t.Fatal("Failed to create new framer:", err)
145
- }
146
- if err := framer.WriteFrame(&synReplyFrame); err != nil {
147
- t.Fatal("WriteFrame with compression:", err)
148
- }
149
- frame, err := framer.ReadFrame()
150
- if err != nil {
151
- t.Fatal("ReadFrame with compression:", err)
152
- }
153
- parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
154
- if !ok {
155
- t.Fatal("Parsed incorrect frame type:", frame)
156
- }
157
- if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
158
- t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
159
- }
160
-}
161
-
162
-func TestCreateParseRstStream(t *testing.T) {
163
- buffer := new(bytes.Buffer)
164
- framer, err := NewFramer(buffer, buffer)
165
- if err != nil {
166
- t.Fatal("Failed to create new framer:", err)
167
- }
168
- rstStreamFrame := RstStreamFrame{
169
- CFHeader: ControlFrameHeader{
170
- version: Version,
171
- frameType: TypeRstStream,
172
- },
173
- StreamId: 1,
174
- Status: InvalidStream,
175
- }
176
- if err := framer.WriteFrame(&rstStreamFrame); err != nil {
177
- t.Fatal("WriteFrame:", err)
178
- }
179
- frame, err := framer.ReadFrame()
180
- if err != nil {
181
- t.Fatal("ReadFrame:", err)
182
- }
183
- parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
184
- if !ok {
185
- t.Fatal("Parsed incorrect frame type:", frame)
186
- }
187
- if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
188
- t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
189
- }
190
-}
191
-
192
-func TestCreateParseSettings(t *testing.T) {
193
- buffer := new(bytes.Buffer)
194
- framer, err := NewFramer(buffer, buffer)
195
- if err != nil {
196
- t.Fatal("Failed to create new framer:", err)
197
- }
198
- settingsFrame := SettingsFrame{
199
- CFHeader: ControlFrameHeader{
200
- version: Version,
201
- frameType: TypeSettings,
202
- },
203
- FlagIdValues: []SettingsFlagIdValue{
204
- {FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
205
- {FlagSettingsPersisted, SettingsUploadBandwidth, 1},
206
- },
207
- }
208
- if err := framer.WriteFrame(&settingsFrame); err != nil {
209
- t.Fatal("WriteFrame:", err)
210
- }
211
- frame, err := framer.ReadFrame()
212
- if err != nil {
213
- t.Fatal("ReadFrame:", err)
214
- }
215
- parsedSettingsFrame, ok := frame.(*SettingsFrame)
216
- if !ok {
217
- t.Fatal("Parsed incorrect frame type:", frame)
218
- }
219
- if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
220
- t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
221
- }
222
-}
223
-
224
-func TestCreateParsePing(t *testing.T) {
225
- buffer := new(bytes.Buffer)
226
- framer, err := NewFramer(buffer, buffer)
227
- if err != nil {
228
- t.Fatal("Failed to create new framer:", err)
229
- }
230
- pingFrame := PingFrame{
231
- CFHeader: ControlFrameHeader{
232
- version: Version,
233
- frameType: TypePing,
234
- },
235
- Id: 31337,
236
- }
237
- if err := framer.WriteFrame(&pingFrame); err != nil {
238
- t.Fatal("WriteFrame:", err)
239
- }
240
- if pingFrame.CFHeader.Flags != 0 {
241
- t.Fatal("Incorrect frame type:", pingFrame)
242
- }
243
- frame, err := framer.ReadFrame()
244
- if err != nil {
245
- t.Fatal("ReadFrame:", err)
246
- }
247
- parsedPingFrame, ok := frame.(*PingFrame)
248
- if !ok {
249
- t.Fatal("Parsed incorrect frame type:", frame)
250
- }
251
- if parsedPingFrame.CFHeader.Flags != 0 {
252
- t.Fatal("Parsed incorrect frame type:", parsedPingFrame)
253
- }
254
- if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
255
- t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
256
- }
257
-}
258
-
259
-func TestCreateParseGoAway(t *testing.T) {
260
- buffer := new(bytes.Buffer)
261
- framer, err := NewFramer(buffer, buffer)
262
- if err != nil {
263
- t.Fatal("Failed to create new framer:", err)
264
- }
265
- goAwayFrame := GoAwayFrame{
266
- CFHeader: ControlFrameHeader{
267
- version: Version,
268
- frameType: TypeGoAway,
269
- },
270
- LastGoodStreamId: 31337,
271
- Status: 1,
272
- }
273
- if err := framer.WriteFrame(&goAwayFrame); err != nil {
274
- t.Fatal("WriteFrame:", err)
275
- }
276
- if goAwayFrame.CFHeader.Flags != 0 {
277
- t.Fatal("Incorrect frame type:", goAwayFrame)
278
- }
279
- if goAwayFrame.CFHeader.length != 8 {
280
- t.Fatal("Incorrect frame type:", goAwayFrame)
281
- }
282
- frame, err := framer.ReadFrame()
283
- if err != nil {
284
- t.Fatal("ReadFrame:", err)
285
- }
286
- parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
287
- if !ok {
288
- t.Fatal("Parsed incorrect frame type:", frame)
289
- }
290
- if parsedGoAwayFrame.CFHeader.Flags != 0 {
291
- t.Fatal("Incorrect frame type:", parsedGoAwayFrame)
292
- }
293
- if parsedGoAwayFrame.CFHeader.length != 8 {
294
- t.Fatal("Incorrect frame type:", parsedGoAwayFrame)
295
- }
296
- if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
297
- t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
298
- }
299
-}
300
-
301
-func TestCreateParseHeadersFrame(t *testing.T) {
302
- buffer := new(bytes.Buffer)
303
- framer := &Framer{
304
- headerCompressionDisabled: true,
305
- w: buffer,
306
- headerBuf: new(bytes.Buffer),
307
- r: buffer,
308
- }
309
- headersFrame := HeadersFrame{
310
- CFHeader: ControlFrameHeader{
311
- version: Version,
312
- frameType: TypeHeaders,
313
- },
314
- StreamId: 2,
315
- }
316
- headersFrame.Headers = HeadersFixture
317
- if err := framer.WriteFrame(&headersFrame); err != nil {
318
- t.Fatal("WriteFrame without compression:", err)
319
- }
320
- frame, err := framer.ReadFrame()
321
- if err != nil {
322
- t.Fatal("ReadFrame without compression:", err)
323
- }
324
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
325
- if !ok {
326
- t.Fatal("Parsed incorrect frame type:", frame)
327
- }
328
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
329
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
330
- }
331
-}
332
-
333
-func TestCreateParseHeadersFrameCompressionEnable(t *testing.T) {
334
- buffer := new(bytes.Buffer)
335
- headersFrame := HeadersFrame{
336
- CFHeader: ControlFrameHeader{
337
- version: Version,
338
- frameType: TypeHeaders,
339
- },
340
- StreamId: 2,
341
- }
342
- headersFrame.Headers = HeadersFixture
343
-
344
- framer, err := NewFramer(buffer, buffer)
345
- if err := framer.WriteFrame(&headersFrame); err != nil {
346
- t.Fatal("WriteFrame with compression:", err)
347
- }
348
- frame, err := framer.ReadFrame()
349
- if err != nil {
350
- t.Fatal("ReadFrame with compression:", err)
351
- }
352
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
353
- if !ok {
354
- t.Fatal("Parsed incorrect frame type:", frame)
355
- }
356
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
357
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
358
- }
359
-}
360
-
361
-func TestCreateParseWindowUpdateFrame(t *testing.T) {
362
- buffer := new(bytes.Buffer)
363
- framer, err := NewFramer(buffer, buffer)
364
- if err != nil {
365
- t.Fatal("Failed to create new framer:", err)
366
- }
367
- windowUpdateFrame := WindowUpdateFrame{
368
- CFHeader: ControlFrameHeader{
369
- version: Version,
370
- frameType: TypeWindowUpdate,
371
- },
372
- StreamId: 31337,
373
- DeltaWindowSize: 1,
374
- }
375
- if err := framer.WriteFrame(&windowUpdateFrame); err != nil {
376
- t.Fatal("WriteFrame:", err)
377
- }
378
- if windowUpdateFrame.CFHeader.Flags != 0 {
379
- t.Fatal("Incorrect frame type:", windowUpdateFrame)
380
- }
381
- if windowUpdateFrame.CFHeader.length != 8 {
382
- t.Fatal("Incorrect frame type:", windowUpdateFrame)
383
- }
384
- frame, err := framer.ReadFrame()
385
- if err != nil {
386
- t.Fatal("ReadFrame:", err)
387
- }
388
- parsedWindowUpdateFrame, ok := frame.(*WindowUpdateFrame)
389
- if !ok {
390
- t.Fatal("Parsed incorrect frame type:", frame)
391
- }
392
- if parsedWindowUpdateFrame.CFHeader.Flags != 0 {
393
- t.Fatal("Incorrect frame type:", parsedWindowUpdateFrame)
394
- }
395
- if parsedWindowUpdateFrame.CFHeader.length != 8 {
396
- t.Fatal("Incorrect frame type:", parsedWindowUpdateFrame)
397
- }
398
- if !reflect.DeepEqual(windowUpdateFrame, *parsedWindowUpdateFrame) {
399
- t.Fatal("got: ", *parsedWindowUpdateFrame, "\nwant: ", windowUpdateFrame)
400
- }
401
-}
402
-
403
-func TestCreateParseDataFrame(t *testing.T) {
404
- buffer := new(bytes.Buffer)
405
- framer, err := NewFramer(buffer, buffer)
406
- if err != nil {
407
- t.Fatal("Failed to create new framer:", err)
408
- }
409
- dataFrame := DataFrame{
410
- StreamId: 1,
411
- Data: []byte{'h', 'e', 'l', 'l', 'o'},
412
- }
413
- if err := framer.WriteFrame(&dataFrame); err != nil {
414
- t.Fatal("WriteFrame:", err)
415
- }
416
- frame, err := framer.ReadFrame()
417
- if err != nil {
418
- t.Fatal("ReadFrame:", err)
419
- }
420
- parsedDataFrame, ok := frame.(*DataFrame)
421
- if !ok {
422
- t.Fatal("Parsed incorrect frame type:", frame)
423
- }
424
- if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
425
- t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
426
- }
427
-}
428
-
429
-func TestCompressionContextAcrossFrames(t *testing.T) {
430
- buffer := new(bytes.Buffer)
431
- framer, err := NewFramer(buffer, buffer)
432
- if err != nil {
433
- t.Fatal("Failed to create new framer:", err)
434
- }
435
- headersFrame := HeadersFrame{
436
- CFHeader: ControlFrameHeader{
437
- version: Version,
438
- frameType: TypeHeaders,
439
- },
440
- StreamId: 2,
441
- Headers: HeadersFixture,
442
- }
443
- if err := framer.WriteFrame(&headersFrame); err != nil {
444
- t.Fatal("WriteFrame (HEADERS):", err)
445
- }
446
- synStreamFrame := SynStreamFrame{
447
- ControlFrameHeader{
448
- Version,
449
- TypeSynStream,
450
- 0, // Flags
451
- 0, // length
452
- },
453
- 2, // StreamId
454
- 0, // AssociatedTOStreamID
455
- 0, // Priority
456
- 1, // Slot
457
- nil, // Headers
458
- }
459
- synStreamFrame.Headers = HeadersFixture
460
-
461
- if err := framer.WriteFrame(&synStreamFrame); err != nil {
462
- t.Fatal("WriteFrame (SYN_STREAM):", err)
463
- }
464
- frame, err := framer.ReadFrame()
465
- if err != nil {
466
- t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
467
- }
468
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
469
- if !ok {
470
- t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
471
- }
472
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
473
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
474
- }
475
- frame, err = framer.ReadFrame()
476
- if err != nil {
477
- t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
478
- }
479
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
480
- if !ok {
481
- t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
482
- }
483
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
484
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
485
- }
486
-}
487
-
488
-func TestMultipleSPDYFrames(t *testing.T) {
489
- // Initialize the framers.
490
- pr1, pw1 := io.Pipe()
491
- pr2, pw2 := io.Pipe()
492
- writer, err := NewFramer(pw1, pr2)
493
- if err != nil {
494
- t.Fatal("Failed to create writer:", err)
495
- }
496
- reader, err := NewFramer(pw2, pr1)
497
- if err != nil {
498
- t.Fatal("Failed to create reader:", err)
499
- }
500
-
501
- // Set up the frames we're actually transferring.
502
- headersFrame := HeadersFrame{
503
- CFHeader: ControlFrameHeader{
504
- version: Version,
505
- frameType: TypeHeaders,
506
- },
507
- StreamId: 2,
508
- Headers: HeadersFixture,
509
- }
510
- synStreamFrame := SynStreamFrame{
511
- CFHeader: ControlFrameHeader{
512
- version: Version,
513
- frameType: TypeSynStream,
514
- },
515
- StreamId: 2,
516
- Headers: HeadersFixture,
517
- }
518
-
519
- // Start the goroutines to write the frames.
520
- go func() {
521
- if err := writer.WriteFrame(&headersFrame); err != nil {
522
- t.Fatal("WriteFrame (HEADERS): ", err)
523
- }
524
- if err := writer.WriteFrame(&synStreamFrame); err != nil {
525
- t.Fatal("WriteFrame (SYN_STREAM): ", err)
526
- }
527
- }()
528
-
529
- // Read the frames and verify they look as expected.
530
- frame, err := reader.ReadFrame()
531
- if err != nil {
532
- t.Fatal("ReadFrame (HEADERS): ", err)
533
- }
534
- parsedHeadersFrame, ok := frame.(*HeadersFrame)
535
- if !ok {
536
- t.Fatal("Parsed incorrect frame type:", frame)
537
- }
538
- if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
539
- t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
540
- }
541
- frame, err = reader.ReadFrame()
542
- if err != nil {
543
- t.Fatal("ReadFrame (SYN_STREAM):", err)
544
- }
545
- parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
546
- if !ok {
547
- t.Fatal("Parsed incorrect frame type.")
548
- }
549
- if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
550
- t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
551
- }
552
-}
553
-
554
-func TestReadMalformedZlibHeader(t *testing.T) {
555
- // These were constructed by corrupting the first byte of the zlib
556
- // header after writing.
557
- malformedStructs := map[string]string{
558
- "SynStreamFrame": "gAIAAQAAABgAAAACAAAAAAAAF/nfolGyYmAAAAAA//8=",
559
- "SynReplyFrame": "gAIAAgAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
560
- "HeadersFrame": "gAIACAAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
561
- }
562
- for name, bad := range malformedStructs {
563
- b, err := base64.StdEncoding.DecodeString(bad)
564
- if err != nil {
565
- t.Errorf("Unable to decode base64 encoded frame %s: %v", name, err)
566
- }
567
- buf := bytes.NewBuffer(b)
568
- reader, err := NewFramer(buf, buf)
569
- if err != nil {
570
- t.Fatalf("NewFramer: %v", err)
571
- }
572
- _, err = reader.ReadFrame()
573
- if err != zlib.ErrHeader {
574
- t.Errorf("Frame %s, expected: %#v, actual: %#v", name, zlib.ErrHeader, err)
575
- }
576
- }
577
-}
578
-
579
-// TODO: these tests are too weak for updating SPDY spec. Fix me.
580
-
581
-type zeroStream struct {
582
- frame Frame
583
- encoded string
584
-}
585
-
586
-var streamIdZeroFrames = map[string]zeroStream{
587
- "SynStreamFrame": {
588
- &SynStreamFrame{StreamId: 0},
589
- "gAIAAQAAABgAAAAAAAAAAAAAePnfolGyYmAAAAAA//8=",
590
- },
591
- "SynReplyFrame": {
592
- &SynReplyFrame{StreamId: 0},
593
- "gAIAAgAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
594
- },
595
- "RstStreamFrame": {
596
- &RstStreamFrame{StreamId: 0},
597
- "gAIAAwAAAAgAAAAAAAAAAA==",
598
- },
599
- "HeadersFrame": {
600
- &HeadersFrame{StreamId: 0},
601
- "gAIACAAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
602
- },
603
- "DataFrame": {
604
- &DataFrame{StreamId: 0},
605
- "AAAAAAAAAAA=",
606
- },
607
- "PingFrame": {
608
- &PingFrame{Id: 0},
609
- "gAIABgAAAAQAAAAA",
610
- },
611
-}
612
-
613
-func TestNoZeroStreamId(t *testing.T) {
614
- t.Log("skipping") // TODO: update to work with SPDY3
615
- return
616
-
617
- for name, f := range streamIdZeroFrames {
618
- b, err := base64.StdEncoding.DecodeString(f.encoded)
619
- if err != nil {
620
- t.Errorf("Unable to decode base64 encoded frame %s: %v", f, err)
621
- continue
622
- }
623
- framer, err := NewFramer(ioutil.Discard, bytes.NewReader(b))
624
- if err != nil {
625
- t.Fatalf("NewFramer: %v", err)
626
- }
627
- err = framer.WriteFrame(f.frame)
628
- checkZeroStreamId(t, name, "WriteFrame", err)
629
-
630
- _, err = framer.ReadFrame()
631
- checkZeroStreamId(t, name, "ReadFrame", err)
632
- }
633
-}
634
-
635
-func checkZeroStreamId(t *testing.T, frame string, method string, err error) {
636
- if err == nil {
637
- t.Errorf("%s ZeroStreamId, no error on %s", method, frame)
638
- return
639
- }
640
- eerr, ok := err.(*Error)
641
- if !ok || eerr.Err != ZeroStreamId {
642
- t.Errorf("%s ZeroStreamId, incorrect error %#v, frame %s", method, eerr, frame)
643
- }
644
-}
Godeps/_workspace/src/code.google.com/p/go.net/spdy/types.go
deleted
-275
@@ -1,275 +0,0 @@
1
-// Copyright 2011 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-// Package spdy implements the SPDY protocol (currently SPDY/3), described in
6
-// http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3.
7
-package spdy
8
-
9
-import (
10
- "bytes"
11
- "compress/zlib"
12
- "io"
13
- "net/http"
14
-)
15
-
16
-// Version is the protocol version number that this package implements.
17
-const Version = 3
18
-
19
-// ControlFrameType stores the type field in a control frame header.
20
-type ControlFrameType uint16
21
-
22
-const (
23
- TypeSynStream ControlFrameType = 0x0001
24
- TypeSynReply = 0x0002
25
- TypeRstStream = 0x0003
26
- TypeSettings = 0x0004
27
- TypePing = 0x0006
28
- TypeGoAway = 0x0007
29
- TypeHeaders = 0x0008
30
- TypeWindowUpdate = 0x0009
31
-)
32
-
33
-// ControlFlags are the flags that can be set on a control frame.
34
-type ControlFlags uint8
35
-
36
-const (
37
- ControlFlagFin ControlFlags = 0x01
38
- ControlFlagUnidirectional = 0x02
39
- ControlFlagSettingsClearSettings = 0x01
40
-)
41
-
42
-// DataFlags are the flags that can be set on a data frame.
43
-type DataFlags uint8
44
-
45
-const (
46
- DataFlagFin DataFlags = 0x01
47
-)
48
-
49
-// MaxDataLength is the maximum number of bytes that can be stored in one frame.
50
-const MaxDataLength = 1<<24 - 1
51
-
52
-// headerValueSepator separates multiple header values.
53
-const headerValueSeparator = "\x00"
54
-
55
-// Frame is a single SPDY frame in its unpacked in-memory representation. Use
56
-// Framer to read and write it.
57
-type Frame interface {
58
- write(f *Framer) error
59
-}
60
-
61
-// ControlFrameHeader contains all the fields in a control frame header,
62
-// in its unpacked in-memory representation.
63
-type ControlFrameHeader struct {
64
- // Note, high bit is the "Control" bit.
65
- version uint16 // spdy version number
66
- frameType ControlFrameType
67
- Flags ControlFlags
68
- length uint32 // length of data field
69
-}
70
-
71
-type controlFrame interface {
72
- Frame
73
- read(h ControlFrameHeader, f *Framer) error
74
-}
75
-
76
-// StreamId represents a 31-bit value identifying the stream.
77
-type StreamId uint32
78
-
79
-// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM
80
-// frame.
81
-type SynStreamFrame struct {
82
- CFHeader ControlFrameHeader
83
- StreamId StreamId
84
- AssociatedToStreamId StreamId // stream id for a stream which this stream is associated to
85
- Priority uint8 // priority of this frame (3-bit)
86
- Slot uint8 // index in the server's credential vector of the client certificate
87
- Headers http.Header
88
-}
89
-
90
-// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame.
91
-type SynReplyFrame struct {
92
- CFHeader ControlFrameHeader
93
- StreamId StreamId
94
- Headers http.Header
95
-}
96
-
97
-// RstStreamStatus represents the status that led to a RST_STREAM.
98
-type RstStreamStatus uint32
99
-
100
-const (
101
- ProtocolError RstStreamStatus = iota + 1
102
- InvalidStream
103
- RefusedStream
104
- UnsupportedVersion
105
- Cancel
106
- InternalError
107
- FlowControlError
108
- StreamInUse
109
- StreamAlreadyClosed
110
- InvalidCredentials
111
- FrameTooLarge
112
-)
113
-
114
-// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM
115
-// frame.
116
-type RstStreamFrame struct {
117
- CFHeader ControlFrameHeader
118
- StreamId StreamId
119
- Status RstStreamStatus
120
-}
121
-
122
-// SettingsFlag represents a flag in a SETTINGS frame.
123
-type SettingsFlag uint8
124
-
125
-const (
126
- FlagSettingsPersistValue SettingsFlag = 0x1
127
- FlagSettingsPersisted = 0x2
128
-)
129
-
130
-// SettingsFlag represents the id of an id/value pair in a SETTINGS frame.
131
-type SettingsId uint32
132
-
133
-const (
134
- SettingsUploadBandwidth SettingsId = iota + 1
135
- SettingsDownloadBandwidth
136
- SettingsRoundTripTime
137
- SettingsMaxConcurrentStreams
138
- SettingsCurrentCwnd
139
- SettingsDownloadRetransRate
140
- SettingsInitialWindowSize
141
- SettingsClientCretificateVectorSize
142
-)
143
-
144
-// SettingsFlagIdValue is the unpacked, in-memory representation of the
145
-// combined flag/id/value for a setting in a SETTINGS frame.
146
-type SettingsFlagIdValue struct {
147
- Flag SettingsFlag
148
- Id SettingsId
149
- Value uint32
150
-}
151
-
152
-// SettingsFrame is the unpacked, in-memory representation of a SPDY
153
-// SETTINGS frame.
154
-type SettingsFrame struct {
155
- CFHeader ControlFrameHeader
156
- FlagIdValues []SettingsFlagIdValue
157
-}
158
-
159
-// PingFrame is the unpacked, in-memory representation of a PING frame.
160
-type PingFrame struct {
161
- CFHeader ControlFrameHeader
162
- Id uint32 // unique id for this ping, from server is even, from client is odd.
163
-}
164
-
165
-// GoAwayStatus represents the status in a GoAwayFrame.
166
-type GoAwayStatus uint32
167
-
168
-const (
169
- GoAwayOK GoAwayStatus = iota
170
- GoAwayProtocolError
171
- GoAwayInternalError
172
-)
173
-
174
-// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame.
175
-type GoAwayFrame struct {
176
- CFHeader ControlFrameHeader
177
- LastGoodStreamId StreamId // last stream id which was accepted by sender
178
- Status GoAwayStatus
179
-}
180
-
181
-// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame.
182
-type HeadersFrame struct {
183
- CFHeader ControlFrameHeader
184
- StreamId StreamId
185
- Headers http.Header
186
-}
187
-
188
-// WindowUpdateFrame is the unpacked, in-memory representation of a
189
-// WINDOW_UPDATE frame.
190
-type WindowUpdateFrame struct {
191
- CFHeader ControlFrameHeader
192
- StreamId StreamId
193
- DeltaWindowSize uint32 // additional number of bytes to existing window size
194
-}
195
-
196
-// TODO: Implement credential frame and related methods.
197
-
198
-// DataFrame is the unpacked, in-memory representation of a DATA frame.
199
-type DataFrame struct {
200
- // Note, high bit is the "Control" bit. Should be 0 for data frames.
201
- StreamId StreamId
202
- Flags DataFlags
203
- Data []byte // payload data of this frame
204
-}
205
-
206
-// A SPDY specific error.
207
-type ErrorCode string
208
-
209
-const (
210
- UnlowercasedHeaderName ErrorCode = "header was not lowercased"
211
- DuplicateHeaders = "multiple headers with same name"
212
- WrongCompressedPayloadSize = "compressed payload size was incorrect"
213
- UnknownFrameType = "unknown frame type"
214
- InvalidControlFrame = "invalid control frame"
215
- InvalidDataFrame = "invalid data frame"
216
- InvalidHeaderPresent = "frame contained invalid header"
217
- ZeroStreamId = "stream id zero is disallowed"
218
-)
219
-
220
-// Error contains both the type of error and additional values. StreamId is 0
221
-// if Error is not associated with a stream.
222
-type Error struct {
223
- Err ErrorCode
224
- StreamId StreamId
225
-}
226
-
227
-func (e *Error) Error() string {
228
- return string(e.Err)
229
-}
230
-
231
-var invalidReqHeaders = map[string]bool{
232
- "Connection": true,
233
- "Host": true,
234
- "Keep-Alive": true,
235
- "Proxy-Connection": true,
236
- "Transfer-Encoding": true,
237
-}
238
-
239
-var invalidRespHeaders = map[string]bool{
240
- "Connection": true,
241
- "Keep-Alive": true,
242
- "Proxy-Connection": true,
243
- "Transfer-Encoding": true,
244
-}
245
-
246
-// Framer handles serializing/deserializing SPDY frames, including compressing/
247
-// decompressing payloads.
248
-type Framer struct {
249
- headerCompressionDisabled bool
250
- w io.Writer
251
- headerBuf *bytes.Buffer
252
- headerCompressor *zlib.Writer
253
- r io.Reader
254
- headerReader io.LimitedReader
255
- headerDecompressor io.ReadCloser
256
-}
257
-
258
-// NewFramer allocates a new Framer for a given SPDY connection, represented by
259
-// a io.Writer and io.Reader. Note that Framer will read and write individual fields
260
-// from/to the Reader and Writer, so the caller should pass in an appropriately
261
-// buffered implementation to optimize performance.
262
-func NewFramer(w io.Writer, r io.Reader) (*Framer, error) {
263
- compressBuf := new(bytes.Buffer)
264
- compressor, err := zlib.NewWriterLevelDict(compressBuf, zlib.BestCompression, []byte(headerDictionary))
265
- if err != nil {
266
- return nil, err
267
- }
268
- framer := &Framer{
269
- w: w,
270
- headerBuf: compressBuf,
271
- headerCompressor: compressor,
272
- r: r,
273
- }
274
- return framer, nil
275
-}
Godeps/_workspace/src/code.google.com/p/go.net/spdy/write.go
deleted
-318
@@ -1,318 +0,0 @@
1
-// Copyright 2011 The Go Authors. All rights reserved.
2
-// Use of this source code is governed by a BSD-style
3
-// license that can be found in the LICENSE file.
4
-
5
-package spdy
6
-
7
-import (
8
- "encoding/binary"
9
- "io"
10
- "net/http"
11
- "strings"
12
-)
13
-
14
-func (frame *SynStreamFrame) write(f *Framer) error {
15
- return f.writeSynStreamFrame(frame)
16
-}
17
-
18
-func (frame *SynReplyFrame) write(f *Framer) error {
19
- return f.writeSynReplyFrame(frame)
20
-}
21
-
22
-func (frame *RstStreamFrame) write(f *Framer) (err error) {
23
- if frame.StreamId == 0 {
24
- return &Error{ZeroStreamId, 0}
25
- }
26
- frame.CFHeader.version = Version
27
- frame.CFHeader.frameType = TypeRstStream
28
- frame.CFHeader.Flags = 0
29
- frame.CFHeader.length = 8
30
-
31
- // Serialize frame to Writer.
32
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
33
- return
34
- }
35
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
36
- return
37
- }
38
- if frame.Status == 0 {
39
- return &Error{InvalidControlFrame, frame.StreamId}
40
- }
41
- if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
42
- return
43
- }
44
- return
45
-}
46
-
47
-func (frame *SettingsFrame) write(f *Framer) (err error) {
48
- frame.CFHeader.version = Version
49
- frame.CFHeader.frameType = TypeSettings
50
- frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
51
-
52
- // Serialize frame to Writer.
53
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
54
- return
55
- }
56
- if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
57
- return
58
- }
59
- for _, flagIdValue := range frame.FlagIdValues {
60
- flagId := uint32(flagIdValue.Flag)<<24 | uint32(flagIdValue.Id)
61
- if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
62
- return
63
- }
64
- if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
65
- return
66
- }
67
- }
68
- return
69
-}
70
-
71
-func (frame *PingFrame) write(f *Framer) (err error) {
72
- if frame.Id == 0 {
73
- return &Error{ZeroStreamId, 0}
74
- }
75
- frame.CFHeader.version = Version
76
- frame.CFHeader.frameType = TypePing
77
- frame.CFHeader.Flags = 0
78
- frame.CFHeader.length = 4
79
-
80
- // Serialize frame to Writer.
81
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
82
- return
83
- }
84
- if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
85
- return
86
- }
87
- return
88
-}
89
-
90
-func (frame *GoAwayFrame) write(f *Framer) (err error) {
91
- frame.CFHeader.version = Version
92
- frame.CFHeader.frameType = TypeGoAway
93
- frame.CFHeader.Flags = 0
94
- frame.CFHeader.length = 8
95
-
96
- // Serialize frame to Writer.
97
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
98
- return
99
- }
100
- if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
101
- return
102
- }
103
- if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
104
- return
105
- }
106
- return nil
107
-}
108
-
109
-func (frame *HeadersFrame) write(f *Framer) error {
110
- return f.writeHeadersFrame(frame)
111
-}
112
-
113
-func (frame *WindowUpdateFrame) write(f *Framer) (err error) {
114
- frame.CFHeader.version = Version
115
- frame.CFHeader.frameType = TypeWindowUpdate
116
- frame.CFHeader.Flags = 0
117
- frame.CFHeader.length = 8
118
-
119
- // Serialize frame to Writer.
120
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
121
- return
122
- }
123
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
124
- return
125
- }
126
- if err = binary.Write(f.w, binary.BigEndian, frame.DeltaWindowSize); err != nil {
127
- return
128
- }
129
- return nil
130
-}
131
-
132
-func (frame *DataFrame) write(f *Framer) error {
133
- return f.writeDataFrame(frame)
134
-}
135
-
136
-// WriteFrame writes a frame.
137
-func (f *Framer) WriteFrame(frame Frame) error {
138
- return frame.write(f)
139
-}
140
-
141
-func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
142
- if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
143
- return err
144
- }
145
- if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
146
- return err
147
- }
148
- flagsAndLength := uint32(h.Flags)<<24 | h.length
149
- if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
150
- return err
151
- }
152
- return nil
153
-}
154
-
155
-func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
156
- n = 0
157
- if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil {
158
- return
159
- }
160
- n += 2
161
- for name, values := range h {
162
- if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil {
163
- return
164
- }
165
- n += 2
166
- name = strings.ToLower(name)
167
- if _, err = io.WriteString(w, name); err != nil {
168
- return
169
- }
170
- n += len(name)
171
- v := strings.Join(values, headerValueSeparator)
172
- if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil {
173
- return
174
- }
175
- n += 2
176
- if _, err = io.WriteString(w, v); err != nil {
177
- return
178
- }
179
- n += len(v)
180
- }
181
- return
182
-}
183
-
184
-func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
185
- if frame.StreamId == 0 {
186
- return &Error{ZeroStreamId, 0}
187
- }
188
- // Marshal the headers.
189
- var writer io.Writer = f.headerBuf
190
- if !f.headerCompressionDisabled {
191
- writer = f.headerCompressor
192
- }
193
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
194
- return
195
- }
196
- if !f.headerCompressionDisabled {
197
- f.headerCompressor.Flush()
198
- }
199
-
200
- // Set ControlFrameHeader.
201
- frame.CFHeader.version = Version
202
- frame.CFHeader.frameType = TypeSynStream
203
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
204
-
205
- // Serialize frame to Writer.
206
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
207
- return err
208
- }
209
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
210
- return err
211
- }
212
- if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
213
- return err
214
- }
215
- if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<5); err != nil {
216
- return err
217
- }
218
- if err = binary.Write(f.w, binary.BigEndian, frame.Slot); err != nil {
219
- return err
220
- }
221
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
222
- return err
223
- }
224
- f.headerBuf.Reset()
225
- return nil
226
-}
227
-
228
-func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
229
- if frame.StreamId == 0 {
230
- return &Error{ZeroStreamId, 0}
231
- }
232
- // Marshal the headers.
233
- var writer io.Writer = f.headerBuf
234
- if !f.headerCompressionDisabled {
235
- writer = f.headerCompressor
236
- }
237
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
238
- return
239
- }
240
- if !f.headerCompressionDisabled {
241
- f.headerCompressor.Flush()
242
- }
243
-
244
- // Set ControlFrameHeader.
245
- frame.CFHeader.version = Version
246
- frame.CFHeader.frameType = TypeSynReply
247
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
248
-
249
- // Serialize frame to Writer.
250
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
251
- return
252
- }
253
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
254
- return
255
- }
256
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
257
- return
258
- }
259
- f.headerBuf.Reset()
260
- return
261
-}
262
-
263
-func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
264
- if frame.StreamId == 0 {
265
- return &Error{ZeroStreamId, 0}
266
- }
267
- // Marshal the headers.
268
- var writer io.Writer = f.headerBuf
269
- if !f.headerCompressionDisabled {
270
- writer = f.headerCompressor
271
- }
272
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
273
- return
274
- }
275
- if !f.headerCompressionDisabled {
276
- f.headerCompressor.Flush()
277
- }
278
-
279
- // Set ControlFrameHeader.
280
- frame.CFHeader.version = Version
281
- frame.CFHeader.frameType = TypeHeaders
282
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
283
-
284
- // Serialize frame to Writer.
285
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
286
- return
287
- }
288
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
289
- return
290
- }
291
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
292
- return
293
- }
294
- f.headerBuf.Reset()
295
- return
296
-}
297
-
298
-func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
299
- if frame.StreamId == 0 {
300
- return &Error{ZeroStreamId, 0}
301
- }
302
- if frame.StreamId&0x80000000 != 0 || len(frame.Data) > MaxDataLength {
303
- return &Error{InvalidDataFrame, frame.StreamId}
304
- }
305
-
306
- // Serialize frame to Writer.
307
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
308
- return
309
- }
310
- flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data))
311
- if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
312
- return
313
- }
314
- if _, err = f.w.Write(frame.Data); err != nil {
315
- return
316
- }
317
- return nil
318
-}
Godeps/_workspace/src/github.com/hashicorp/yamux/.gitignore
new
+23
@@ -0,0 +1,23 @@
1
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
2
+*.o
3
+*.a
4
+*.so
5
+
6
+# Folders
7
+_obj
8
+_test
9
+
10
+# Architecture specific extensions/prefixes
11
+*.[568vq]
12
+[568vq].out
13
+
14
+*.cgo1.go
15
+*.cgo2.c
16
+_cgo_defun.c
17
+_cgo_gotypes.go
18
+_cgo_export.*
19
+
20
+_testmain.go
21
+
22
+*.exe
23
+*.test
Godeps/_workspace/src/github.com/hashicorp/yamux/LICENSE
new
+362
@@ -0,0 +1,362 @@
1
+Mozilla Public License, version 2.0
2
+
3
+1. Definitions
4
+
5
+1.1. "Contributor"
6
+
7
+ means each individual or legal entity that creates, contributes to the
8
+ creation of, or owns Covered Software.
9
+
10
+1.2. "Contributor Version"
11
+
12
+ means the combination of the Contributions of others (if any) used by a
13
+ Contributor and that particular Contributor's Contribution.
14
+
15
+1.3. "Contribution"
16
+
17
+ means Covered Software of a particular Contributor.
18
+
19
+1.4. "Covered Software"
20
+
21
+ means Source Code Form to which the initial Contributor has attached the
22
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
23
+ Modifications of such Source Code Form, in each case including portions
24
+ thereof.
25
+
26
+1.5. "Incompatible With Secondary Licenses"
27
+ means
28
+
29
+ a. that the initial Contributor has attached the notice described in
30
+ Exhibit B to the Covered Software; or
31
+
32
+ b. that the Covered Software was made available under the terms of
33
+ version 1.1 or earlier of the License, but not also under the terms of
34
+ a Secondary License.
35
+
36
+1.6. "Executable Form"
37
+
38
+ means any form of the work other than Source Code Form.
39
+
40
+1.7. "Larger Work"
41
+
42
+ means a work that combines Covered Software with other material, in a
43
+ separate file or files, that is not Covered Software.
44
+
45
+1.8. "License"
46
+
47
+ means this document.
48
+
49
+1.9. "Licensable"
50
+
51
+ means having the right to grant, to the maximum extent possible, whether
52
+ at the time of the initial grant or subsequently, any and all of the
53
+ rights conveyed by this License.
54
+
55
+1.10. "Modifications"
56
+
57
+ means any of the following:
58
+
59
+ a. any file in Source Code Form that results from an addition to,
60
+ deletion from, or modification of the contents of Covered Software; or
61
+
62
+ b. any new file in Source Code Form that contains any Covered Software.
63
+
64
+1.11. "Patent Claims" of a Contributor
65
+
66
+ means any patent claim(s), including without limitation, method,
67
+ process, and apparatus claims, in any patent Licensable by such
68
+ Contributor that would be infringed, but for the grant of the License,
69
+ by the making, using, selling, offering for sale, having made, import,
70
+ or transfer of either its Contributions or its Contributor Version.
71
+
72
+1.12. "Secondary License"
73
+
74
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
75
+ General Public License, Version 2.1, the GNU Affero General Public
76
+ License, Version 3.0, or any later versions of those licenses.
77
+
78
+1.13. "Source Code Form"
79
+
80
+ means the form of the work preferred for making modifications.
81
+
82
+1.14. "You" (or "Your")
83
+
84
+ means an individual or a legal entity exercising rights under this
85
+ License. For legal entities, "You" includes any entity that controls, is
86
+ controlled by, or is under common control with You. For purposes of this
87
+ definition, "control" means (a) the power, direct or indirect, to cause
88
+ the direction or management of such entity, whether by contract or
89
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
90
+ outstanding shares or beneficial ownership of such entity.
91
+
92
+
93
+2. License Grants and Conditions
94
+
95
+2.1. Grants
96
+
97
+ Each Contributor hereby grants You a world-wide, royalty-free,
98
+ non-exclusive license:
99
+
100
+ a. under intellectual property rights (other than patent or trademark)
101
+ Licensable by such Contributor to use, reproduce, make available,
102
+ modify, display, perform, distribute, and otherwise exploit its
103
+ Contributions, either on an unmodified basis, with Modifications, or
104
+ as part of a Larger Work; and
105
+
106
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
107
+ sale, have made, import, and otherwise transfer either its
108
+ Contributions or its Contributor Version.
109
+
110
+2.2. Effective Date
111
+
112
+ The licenses granted in Section 2.1 with respect to any Contribution
113
+ become effective for each Contribution on the date the Contributor first
114
+ distributes such Contribution.
115
+
116
+2.3. Limitations on Grant Scope
117
+
118
+ The licenses granted in this Section 2 are the only rights granted under
119
+ this License. No additional rights or licenses will be implied from the
120
+ distribution or licensing of Covered Software under this License.
121
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
122
+ Contributor:
123
+
124
+ a. for any code that a Contributor has removed from Covered Software; or
125
+
126
+ b. for infringements caused by: (i) Your and any other third party's
127
+ modifications of Covered Software, or (ii) the combination of its
128
+ Contributions with other software (except as part of its Contributor
129
+ Version); or
130
+
131
+ c. under Patent Claims infringed by Covered Software in the absence of
132
+ its Contributions.
133
+
134
+ This License does not grant any rights in the trademarks, service marks,
135
+ or logos of any Contributor (except as may be necessary to comply with
136
+ the notice requirements in Section 3.4).
137
+
138
+2.4. Subsequent Licenses
139
+
140
+ No Contributor makes additional grants as a result of Your choice to
141
+ distribute the Covered Software under a subsequent version of this
142
+ License (see Section 10.2) or under the terms of a Secondary License (if
143
+ permitted under the terms of Section 3.3).
144
+
145
+2.5. Representation
146
+
147
+ Each Contributor represents that the Contributor believes its
148
+ Contributions are its original creation(s) or it has sufficient rights to
149
+ grant the rights to its Contributions conveyed by this License.
150
+
151
+2.6. Fair Use
152
+
153
+ This License is not intended to limit any rights You have under
154
+ applicable copyright doctrines of fair use, fair dealing, or other
155
+ equivalents.
156
+
157
+2.7. Conditions
158
+
159
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
160
+ Section 2.1.
161
+
162
+
163
+3. Responsibilities
164
+
165
+3.1. Distribution of Source Form
166
+
167
+ All distribution of Covered Software in Source Code Form, including any
168
+ Modifications that You create or to which You contribute, must be under
169
+ the terms of this License. You must inform recipients that the Source
170
+ Code Form of the Covered Software is governed by the terms of this
171
+ License, and how they can obtain a copy of this License. You may not
172
+ attempt to alter or restrict the recipients' rights in the Source Code
173
+ Form.
174
+
175
+3.2. Distribution of Executable Form
176
+
177
+ If You distribute Covered Software in Executable Form then:
178
+
179
+ a. such Covered Software must also be made available in Source Code Form,
180
+ as described in Section 3.1, and You must inform recipients of the
181
+ Executable Form how they can obtain a copy of such Source Code Form by
182
+ reasonable means in a timely manner, at a charge no more than the cost
183
+ of distribution to the recipient; and
184
+
185
+ b. You may distribute such Executable Form under the terms of this
186
+ License, or sublicense it under different terms, provided that the
187
+ license for the Executable Form does not attempt to limit or alter the
188
+ recipients' rights in the Source Code Form under this License.
189
+
190
+3.3. Distribution of a Larger Work
191
+
192
+ You may create and distribute a Larger Work under terms of Your choice,
193
+ provided that You also comply with the requirements of this License for
194
+ the Covered Software. If the Larger Work is a combination of Covered
195
+ Software with a work governed by one or more Secondary Licenses, and the
196
+ Covered Software is not Incompatible With Secondary Licenses, this
197
+ License permits You to additionally distribute such Covered Software
198
+ under the terms of such Secondary License(s), so that the recipient of
199
+ the Larger Work may, at their option, further distribute the Covered
200
+ Software under the terms of either this License or such Secondary
201
+ License(s).
202
+
203
+3.4. Notices
204
+
205
+ You may not remove or alter the substance of any license notices
206
+ (including copyright notices, patent notices, disclaimers of warranty, or
207
+ limitations of liability) contained within the Source Code Form of the
208
+ Covered Software, except that You may alter any license notices to the
209
+ extent required to remedy known factual inaccuracies.
210
+
211
+3.5. Application of Additional Terms
212
+
213
+ You may choose to offer, and to charge a fee for, warranty, support,
214
+ indemnity or liability obligations to one or more recipients of Covered
215
+ Software. However, You may do so only on Your own behalf, and not on
216
+ behalf of any Contributor. You must make it absolutely clear that any
217
+ such warranty, support, indemnity, or liability obligation is offered by
218
+ You alone, and You hereby agree to indemnify every Contributor for any
219
+ liability incurred by such Contributor as a result of warranty, support,
220
+ indemnity or liability terms You offer. You may include additional
221
+ disclaimers of warranty and limitations of liability specific to any
222
+ jurisdiction.
223
+
224
+4. Inability to Comply Due to Statute or Regulation
225
+
226
+ If it is impossible for You to comply with any of the terms of this License
227
+ with respect to some or all of the Covered Software due to statute,
228
+ judicial order, or regulation then You must: (a) comply with the terms of
229
+ this License to the maximum extent possible; and (b) describe the
230
+ limitations and the code they affect. Such description must be placed in a
231
+ text file included with all distributions of the Covered Software under
232
+ this License. Except to the extent prohibited by statute or regulation,
233
+ such description must be sufficiently detailed for a recipient of ordinary
234
+ skill to be able to understand it.
235
+
236
+5. Termination
237
+
238
+5.1. The rights granted under this License will terminate automatically if You
239
+ fail to comply with any of its terms. However, if You become compliant,
240
+ then the rights granted under this License from a particular Contributor
241
+ are reinstated (a) provisionally, unless and until such Contributor
242
+ explicitly and finally terminates Your grants, and (b) on an ongoing
243
+ basis, if such Contributor fails to notify You of the non-compliance by
244
+ some reasonable means prior to 60 days after You have come back into
245
+ compliance. Moreover, Your grants from a particular Contributor are
246
+ reinstated on an ongoing basis if such Contributor notifies You of the
247
+ non-compliance by some reasonable means, this is the first time You have
248
+ received notice of non-compliance with this License from such
249
+ Contributor, and You become compliant prior to 30 days after Your receipt
250
+ of the notice.
251
+
252
+5.2. If You initiate litigation against any entity by asserting a patent
253
+ infringement claim (excluding declaratory judgment actions,
254
+ counter-claims, and cross-claims) alleging that a Contributor Version
255
+ directly or indirectly infringes any patent, then the rights granted to
256
+ You by any and all Contributors for the Covered Software under Section
257
+ 2.1 of this License shall terminate.
258
+
259
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
260
+ license agreements (excluding distributors and resellers) which have been
261
+ validly granted by You or Your distributors under this License prior to
262
+ termination shall survive termination.
263
+
264
+6. Disclaimer of Warranty
265
+
266
+ Covered Software is provided under this License on an "as is" basis,
267
+ without warranty of any kind, either expressed, implied, or statutory,
268
+ including, without limitation, warranties that the Covered Software is free
269
+ of defects, merchantable, fit for a particular purpose or non-infringing.
270
+ The entire risk as to the quality and performance of the Covered Software
271
+ is with You. Should any Covered Software prove defective in any respect,
272
+ You (not any Contributor) assume the cost of any necessary servicing,
273
+ repair, or correction. This disclaimer of warranty constitutes an essential
274
+ part of this License. No use of any Covered Software is authorized under
275
+ this License except under this disclaimer.
276
+
277
+7. Limitation of Liability
278
+
279
+ Under no circumstances and under no legal theory, whether tort (including
280
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
281
+ distributes Covered Software as permitted above, be liable to You for any
282
+ direct, indirect, special, incidental, or consequential damages of any
283
+ character including, without limitation, damages for lost profits, loss of
284
+ goodwill, work stoppage, computer failure or malfunction, or any and all
285
+ other commercial damages or losses, even if such party shall have been
286
+ informed of the possibility of such damages. This limitation of liability
287
+ shall not apply to liability for death or personal injury resulting from
288
+ such party's negligence to the extent applicable law prohibits such
289
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
290
+ incidental or consequential damages, so this exclusion and limitation may
291
+ not apply to You.
292
+
293
+8. Litigation
294
+
295
+ Any litigation relating to this License may be brought only in the courts
296
+ of a jurisdiction where the defendant maintains its principal place of
297
+ business and such litigation shall be governed by laws of that
298
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
299
+ in this Section shall prevent a party's ability to bring cross-claims or
300
+ counter-claims.
301
+
302
+9. Miscellaneous
303
+
304
+ This License represents the complete agreement concerning the subject
305
+ matter hereof. If any provision of this License is held to be
306
+ unenforceable, such provision shall be reformed only to the extent
307
+ necessary to make it enforceable. Any law or regulation which provides that
308
+ the language of a contract shall be construed against the drafter shall not
309
+ be used to construe this License against a Contributor.
310
+
311
+
312
+10. Versions of the License
313
+
314
+10.1. New Versions
315
+
316
+ Mozilla Foundation is the license steward. Except as provided in Section
317
+ 10.3, no one other than the license steward has the right to modify or
318
+ publish new versions of this License. Each version will be given a
319
+ distinguishing version number.
320
+
321
+10.2. Effect of New Versions
322
+
323
+ You may distribute the Covered Software under the terms of the version
324
+ of the License under which You originally received the Covered Software,
325
+ or under the terms of any subsequent version published by the license
326
+ steward.
327
+
328
+10.3. Modified Versions
329
+
330
+ If you create software not governed by this License, and you want to
331
+ create a new license for such software, you may create and use a
332
+ modified version of this License if you rename the license and remove
333
+ any references to the name of the license steward (except to note that
334
+ such modified license differs from this License).
335
+
336
+10.4. Distributing Source Code Form that is Incompatible With Secondary
337
+ Licenses If You choose to distribute Source Code Form that is
338
+ Incompatible With Secondary Licenses under the terms of this version of
339
+ the License, the notice described in Exhibit B of this License must be
340
+ attached.
341
+
342
+Exhibit A - Source Code Form License Notice
343
+
344
+ This Source Code Form is subject to the
345
+ terms of the Mozilla Public License, v.
346
+ 2.0. If a copy of the MPL was not
347
+ distributed with this file, You can
348
+ obtain one at
349
+ http://mozilla.org/MPL/2.0/.
350
+
351
+If it is not possible or desirable to put the notice in a particular file,
352
+then You may include the notice in a location (such as a LICENSE file in a
353
+relevant directory) where a recipient would be likely to look for such a
354
+notice.
355
+
356
+You may add additional accurate notices of copyright ownership.
357
+
358
+Exhibit B - "Incompatible With Secondary Licenses" Notice
359
+
360
+ This Source Code Form is "Incompatible
361
+ With Secondary Licenses", as defined by
362
+ the Mozilla Public License, v. 2.0.
\ No newline at end of file
Godeps/_workspace/src/github.com/hashicorp/yamux/README.md
new
+86
@@ -0,0 +1,86 @@
1
+# Yamux
2
+
3
+Yamux (Yet another Multiplexer) is a multiplexing library for Golang.
4
+It relies on an underlying connection to provide reliability
5
+and ordering, such as TCP or Unix domain sockets, and provides
6
+stream-oriented multiplexing. It is inspired by SPDY but is not
7
+interoperable with it.
8
+
9
+Yamux features include:
10
+
11
+* Bi-directional streams
12
+ * Streams can be opened by either client or server
13
+ * Useful for NAT traversal
14
+ * Server-side push support
15
+* Flow control
16
+ * Avoid starvation
17
+ * Back-pressure to prevent overwhelming a receiver
18
+* Keep Alives
19
+ * Enables persistent connections over a load balancer
20
+* Efficient
21
+ * Enables thousands of logical streams with low overhead
22
+
23
+## Documentation
24
+
25
+For complete documentation, see the associated [Godoc](http://godoc.org/github.com/hashicorp/yamux).
26
+
27
+## Specification
28
+
29
+The full specification for Yamux is provided in the `spec.md` file.
30
+It can be used as a guide to implementors of interoperable libraries.
31
+
32
+## Usage
33
+
34
+Using Yamux is remarkably simple:
35
+
36
+```go
37
+
38
+func client() {
39
+ // Get a TCP connection
40
+ conn, err := net.Dial(...)
41
+ if err != nil {
42
+ panic(err)
43
+ }
44
+
45
+ // Setup client side of yamux
46
+ session, err := yamux.Client(conn, nil)
47
+ if err != nil {
48
+ panic(err)
49
+ }
50
+
51
+ // Open a new stream
52
+ stream, err := session.Open()
53
+ if err != nil {
54
+ panic(err)
55
+ }
56
+
57
+ // Stream implements net.Conn
58
+ stream.Write([]byte("ping"))
59
+}
60
+
61
+func server() {
62
+ // Accept a TCP connection
63
+ conn, err := listener.Accept()
64
+ if err != nil {
65
+ panic(err)
66
+ }
67
+
68
+ // Setup server side of yamux
69
+ session, err := yamux.Server(conn, nil)
70
+ if err != nil {
71
+ panic(err)
72
+ }
73
+
74
+ // Accept a stream
75
+ stream, err := session.Accept()
76
+ if err != nil {
77
+ panic(err)
78
+ }
79
+
80
+ // Listen for a message
81
+ buf := make([]byte, 4)
82
+ stream.Read(buf)
83
+}
84
+
85
+```
86
+
Godeps/_workspace/src/github.com/hashicorp/yamux/addr.go
new
+60
@@ -0,0 +1,60 @@
1
+package yamux
2
+
3
+import (
4
+ "fmt"
5
+ "net"
6
+)
7
+
8
+// hasAddr is used to get the address from the underlying connection
9
+type hasAddr interface {
10
+ LocalAddr() net.Addr
11
+ RemoteAddr() net.Addr
12
+}
13
+
14
+// yamuxAddr is used when we cannot get the underlying address
15
+type yamuxAddr struct {
16
+ Addr string
17
+}
18
+
19
+func (*yamuxAddr) Network() string {
20
+ return "yamux"
21
+}
22
+
23
+func (y *yamuxAddr) String() string {
24
+ return fmt.Sprintf("yamux:%s", y.Addr)
25
+}
26
+
27
+// Addr is used to get the address of the listener.
28
+func (s *Session) Addr() net.Addr {
29
+ return s.LocalAddr()
30
+}
31
+
32
+// LocalAddr is used to get the local address of the
33
+// underlying connection.
34
+func (s *Session) LocalAddr() net.Addr {
35
+ addr, ok := s.conn.(hasAddr)
36
+ if !ok {
37
+ return &yamuxAddr{"local"}
38
+ }
39
+ return addr.LocalAddr()
40
+}
41
+
42
+// RemoteAddr is used to get the address of remote end
43
+// of the underlying connection
44
+func (s *Session) RemoteAddr() net.Addr {
45
+ addr, ok := s.conn.(hasAddr)
46
+ if !ok {
47
+ return &yamuxAddr{"remote"}
48
+ }
49
+ return addr.RemoteAddr()
50
+}
51
+
52
+// LocalAddr returns the local address
53
+func (s *Stream) LocalAddr() net.Addr {
54
+ return s.session.LocalAddr()
55
+}
56
+
57
+// LocalAddr returns the remote address
58
+func (s *Stream) RemoteAddr() net.Addr {
59
+ return s.session.RemoteAddr()
60
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/bench_test.go
new
+81
@@ -0,0 +1,81 @@
1
+package yamux
2
+
3
+import (
4
+ "testing"
5
+)
6
+
7
+func BenchmarkPing(b *testing.B) {
8
+ client, server := testClientServer()
9
+ defer client.Close()
10
+ defer server.Close()
11
+
12
+ for i := 0; i < b.N; i++ {
13
+ rtt, err := client.Ping()
14
+ if err != nil {
15
+ b.Fatalf("err: %v", err)
16
+ }
17
+ if rtt == 0 {
18
+ b.Fatalf("bad: %v", rtt)
19
+ }
20
+ }
21
+}
22
+
23
+func BenchmarkAccept(b *testing.B) {
24
+ client, server := testClientServer()
25
+ defer client.Close()
26
+ defer server.Close()
27
+
28
+ go func() {
29
+ for i := 0; i < b.N; i++ {
30
+ stream, err := server.AcceptStream()
31
+ if err != nil {
32
+ return
33
+ }
34
+ stream.Close()
35
+ }
36
+ }()
37
+
38
+ for i := 0; i < b.N; i++ {
39
+ stream, err := client.Open()
40
+ if err != nil {
41
+ b.Fatalf("err: %v", err)
42
+ }
43
+ stream.Close()
44
+ }
45
+}
46
+
47
+func BenchmarkSendRecv(b *testing.B) {
48
+ client, server := testClientServer()
49
+ defer client.Close()
50
+ defer server.Close()
51
+
52
+ sendBuf := make([]byte, 512)
53
+ recvBuf := make([]byte, 512)
54
+
55
+ doneCh := make(chan struct{})
56
+ go func() {
57
+ stream, err := server.AcceptStream()
58
+ if err != nil {
59
+ return
60
+ }
61
+ defer stream.Close()
62
+ for i := 0; i < b.N; i++ {
63
+ if _, err := stream.Read(recvBuf); err != nil {
64
+ b.Fatalf("err: %v", err)
65
+ }
66
+ }
67
+ close(doneCh)
68
+ }()
69
+
70
+ stream, err := client.Open()
71
+ if err != nil {
72
+ b.Fatalf("err: %v", err)
73
+ }
74
+ defer stream.Close()
75
+ for i := 0; i < b.N; i++ {
76
+ if _, err := stream.Write(sendBuf); err != nil {
77
+ b.Fatalf("err: %v", err)
78
+ }
79
+ }
80
+ <-doneCh
81
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/const.go
new
+150
@@ -0,0 +1,150 @@
1
+package yamux
2
+
3
+import (
4
+ "encoding/binary"
5
+ "fmt"
6
+)
7
+
8
+var (
9
+ // ErrInvalidVersion means we received a frame with an
10
+ // invalid version
11
+ ErrInvalidVersion = fmt.Errorf("invalid protocol version")
12
+
13
+ // ErrInvalidMsgType means we received a frame with an
14
+ // invalid message type
15
+ ErrInvalidMsgType = fmt.Errorf("invalid msg type")
16
+
17
+ // ErrSessionShutdown is used if there is a shutdown during
18
+ // an operation
19
+ ErrSessionShutdown = fmt.Errorf("session shutdown")
20
+
21
+ // ErrStreamsExhausted is returned if we have no more
22
+ // stream ids to issue
23
+ ErrStreamsExhausted = fmt.Errorf("streams exhausted")
24
+
25
+ // ErrDuplicateStream is used if a duplicate stream is
26
+ // opened inbound
27
+ ErrDuplicateStream = fmt.Errorf("duplicate stream initiated")
28
+
29
+ // ErrReceiveWindowExceeded indicates the window was exceeded
30
+ ErrRecvWindowExceeded = fmt.Errorf("recv window exceeded")
31
+
32
+ // ErrTimeout is used when we reach an IO deadline
33
+ ErrTimeout = fmt.Errorf("i/o deadline reached")
34
+
35
+ // ErrStreamClosed is returned when using a closed stream
36
+ ErrStreamClosed = fmt.Errorf("stream closed")
37
+
38
+ // ErrUnexpectedFlag is set when we get an unexpected flag
39
+ ErrUnexpectedFlag = fmt.Errorf("unexpected flag")
40
+
41
+ // ErrRemoteGoAway is used when we get a go away from the other side
42
+ ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections")
43
+
44
+ // ErrConnectionReset is sent if a stream is reset. This can happen
45
+ // if the backlog is exceeded, or if there was a remote GoAway.
46
+ ErrConnectionReset = fmt.Errorf("connection reset")
47
+)
48
+
49
+const (
50
+ // protoVersion is the only version we support
51
+ protoVersion uint8 = 0
52
+)
53
+
54
+const (
55
+ // Data is used for data frames. They are followed
56
+ // by length bytes worth of payload.
57
+ typeData uint8 = iota
58
+
59
+ // WindowUpdate is used to change the window of
60
+ // a given stream. The length indicates the delta
61
+ // update to the window.
62
+ typeWindowUpdate
63
+
64
+ // Ping is sent as a keep-alive or to measure
65
+ // the RTT. The StreamID and Length value are echoed
66
+ // back in the response.
67
+ typePing
68
+
69
+ // GoAway is sent to terminate a session. The StreamID
70
+ // should be 0 and the length is an error code.
71
+ typeGoAway
72
+)
73
+
74
+const (
75
+ // SYN is sent to signal a new stream. May
76
+ // be sent with a data payload
77
+ flagSYN uint16 = 1 << iota
78
+
79
+ // ACK is sent to acknowledge a new stream. May
80
+ // be sent with a data payload
81
+ flagACK
82
+
83
+ // FIN is sent to half-close the given stream.
84
+ // May be sent with a data payload.
85
+ flagFIN
86
+
87
+ // RST is used to hard close a given stream.
88
+ flagRST
89
+)
90
+
91
+const (
92
+ // initialStreamWindow is the initial stream window size
93
+ initialStreamWindow uint32 = 256 * 1024
94
+)
95
+
96
+const (
97
+ // goAwayNormal is sent on a normal termination
98
+ goAwayNormal uint32 = iota
99
+
100
+ // goAwayProtoErr sent on a protocol error
101
+ goAwayProtoErr
102
+
103
+ // goAwayInternalErr sent on an internal error
104
+ goAwayInternalErr
105
+)
106
+
107
+const (
108
+ sizeOfVersion = 1
109
+ sizeOfType = 1
110
+ sizeOfFlags = 2
111
+ sizeOfStreamID = 4
112
+ sizeOfLength = 4
113
+ headerSize = sizeOfVersion + sizeOfType + sizeOfFlags +
114
+ sizeOfStreamID + sizeOfLength
115
+)
116
+
117
+type header []byte
118
+
119
+func (h header) Version() uint8 {
120
+ return h[0]
121
+}
122
+
123
+func (h header) MsgType() uint8 {
124
+ return h[1]
125
+}
126
+
127
+func (h header) Flags() uint16 {
128
+ return binary.BigEndian.Uint16(h[2:4])
129
+}
130
+
131
+func (h header) StreamID() uint32 {
132
+ return binary.BigEndian.Uint32(h[4:8])
133
+}
134
+
135
+func (h header) Length() uint32 {
136
+ return binary.BigEndian.Uint32(h[8:12])
137
+}
138
+
139
+func (h header) String() string {
140
+ return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d",
141
+ h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length())
142
+}
143
+
144
+func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) {
145
+ h[0] = protoVersion
146
+ h[1] = msgType
147
+ binary.BigEndian.PutUint16(h[2:4], flags)
148
+ binary.BigEndian.PutUint32(h[4:8], streamID)
149
+ binary.BigEndian.PutUint32(h[8:12], length)
150
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/const_test.go
new
+72
@@ -0,0 +1,72 @@
1
+package yamux
2
+
3
+import (
4
+ "testing"
5
+)
6
+
7
+func TestConst(t *testing.T) {
8
+ if protoVersion != 0 {
9
+ t.Fatalf("bad: %v", protoVersion)
10
+ }
11
+
12
+ if typeData != 0 {
13
+ t.Fatalf("bad: %v", typeData)
14
+ }
15
+ if typeWindowUpdate != 1 {
16
+ t.Fatalf("bad: %v", typeWindowUpdate)
17
+ }
18
+ if typePing != 2 {
19
+ t.Fatalf("bad: %v", typePing)
20
+ }
21
+ if typeGoAway != 3 {
22
+ t.Fatalf("bad: %v", typeGoAway)
23
+ }
24
+
25
+ if flagSYN != 1 {
26
+ t.Fatalf("bad: %v", flagSYN)
27
+ }
28
+ if flagACK != 2 {
29
+ t.Fatalf("bad: %v", flagACK)
30
+ }
31
+ if flagFIN != 4 {
32
+ t.Fatalf("bad: %v", flagFIN)
33
+ }
34
+ if flagRST != 8 {
35
+ t.Fatalf("bad: %v", flagRST)
36
+ }
37
+
38
+ if goAwayNormal != 0 {
39
+ t.Fatalf("bad: %v", goAwayNormal)
40
+ }
41
+ if goAwayProtoErr != 1 {
42
+ t.Fatalf("bad: %v", goAwayProtoErr)
43
+ }
44
+ if goAwayInternalErr != 2 {
45
+ t.Fatalf("bad: %v", goAwayInternalErr)
46
+ }
47
+
48
+ if headerSize != 12 {
49
+ t.Fatalf("bad header size")
50
+ }
51
+}
52
+
53
+func TestEncodeDecode(t *testing.T) {
54
+ hdr := header(make([]byte, headerSize))
55
+ hdr.encode(typeWindowUpdate, flagACK|flagRST, 1234, 4321)
56
+
57
+ if hdr.Version() != protoVersion {
58
+ t.Fatalf("bad: %v", hdr)
59
+ }
60
+ if hdr.MsgType() != typeWindowUpdate {
61
+ t.Fatalf("bad: %v", hdr)
62
+ }
63
+ if hdr.Flags() != flagACK|flagRST {
64
+ t.Fatalf("bad: %v", hdr)
65
+ }
66
+ if hdr.StreamID() != 1234 {
67
+ t.Fatalf("bad: %v", hdr)
68
+ }
69
+ if hdr.Length() != 4321 {
70
+ t.Fatalf("bad: %v", hdr)
71
+ }
72
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/mux.go
new
+80
@@ -0,0 +1,80 @@
1
+package yamux
2
+
3
+import (
4
+ "fmt"
5
+ "io"
6
+ "os"
7
+ "time"
8
+)
9
+
10
+// Config is used to tune the Yamux session
11
+type Config struct {
12
+ // AcceptBacklog is used to limit how many streams may be
13
+ // waiting an accept.
14
+ AcceptBacklog int
15
+
16
+ // EnableKeepalive is used to do a period keep alive
17
+ // messages using a ping.
18
+ EnableKeepAlive bool
19
+
20
+ // KeepAliveInterval is how often to perform the keep alive
21
+ KeepAliveInterval time.Duration
22
+
23
+ // MaxStreamWindowSize is used to control the maximum
24
+ // window size that we allow for a stream.
25
+ MaxStreamWindowSize uint32
26
+
27
+ // LogOutput is used to control the log destination
28
+ LogOutput io.Writer
29
+}
30
+
31
+// DefaultConfig is used to return a default configuration
32
+func DefaultConfig() *Config {
33
+ return &Config{
34
+ AcceptBacklog: 256,
35
+ EnableKeepAlive: true,
36
+ KeepAliveInterval: 30 * time.Second,
37
+ MaxStreamWindowSize: initialStreamWindow,
38
+ LogOutput: os.Stderr,
39
+ }
40
+}
41
+
42
+// VerifyConfig is used to verify the sanity of configuration
43
+func VerifyConfig(config *Config) error {
44
+ if config.AcceptBacklog <= 0 {
45
+ return fmt.Errorf("backlog must be positive")
46
+ }
47
+ if config.KeepAliveInterval == 0 {
48
+ return fmt.Errorf("keep-alive interval must be positive")
49
+ }
50
+ if config.MaxStreamWindowSize < initialStreamWindow {
51
+ return fmt.Errorf("MaxStreamWindowSize must be larger than %d", initialStreamWindow)
52
+ }
53
+ return nil
54
+}
55
+
56
+// Server is used to initialize a new server-side connection.
57
+// There must be at most one server-side connection. If a nil config is
58
+// provided, the DefaultConfiguration will be used.
59
+func Server(conn io.ReadWriteCloser, config *Config) (*Session, error) {
60
+ if config == nil {
61
+ config = DefaultConfig()
62
+ }
63
+ if err := VerifyConfig(config); err != nil {
64
+ return nil, err
65
+ }
66
+ return newSession(config, conn, false), nil
67
+}
68
+
69
+// Client is used to initialize a new client-side connection.
70
+// There must be at most one client-side connection.
71
+func Client(conn io.ReadWriteCloser, config *Config) (*Session, error) {
72
+ if config == nil {
73
+ config = DefaultConfig()
74
+ }
75
+
76
+ if err := VerifyConfig(config); err != nil {
77
+ return nil, err
78
+ }
79
+ return newSession(config, conn, true), nil
80
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/session.go
new
+505
@@ -0,0 +1,505 @@
1
+package yamux
2
+
3
+import (
4
+ "bufio"
5
+ "fmt"
6
+ "io"
7
+ "io/ioutil"
8
+ "log"
9
+ "math"
10
+ "net"
11
+ "strings"
12
+ "sync"
13
+ "sync/atomic"
14
+ "time"
15
+)
16
+
17
+// Session is used to wrap a reliable ordered connection and to
18
+// multiplex it into multiple streams.
19
+type Session struct {
20
+ // remoteGoAway indicates the remote side does
21
+ // not want futher connections. Must be first for alignment.
22
+ remoteGoAway int32
23
+
24
+ // localGoAway indicates that we should stop
25
+ // accepting futher connections. Must be first for alignment.
26
+ localGoAway int32
27
+
28
+ // nextStreamID is the next stream we should
29
+ // send. This depends if we are a client/server.
30
+ nextStreamID uint32
31
+
32
+ // config holds our configuration
33
+ config *Config
34
+
35
+ // logger is used for our logs
36
+ logger *log.Logger
37
+
38
+ // conn is the underlying connection
39
+ conn io.ReadWriteCloser
40
+
41
+ // bufRead is a buffered reader
42
+ bufRead *bufio.Reader
43
+
44
+ // pings is used to track inflight pings
45
+ pings map[uint32]chan struct{}
46
+ pingID uint32
47
+ pingLock sync.Mutex
48
+
49
+ // streams maps a stream id to a stream
50
+ streams map[uint32]*Stream
51
+ streamLock sync.Mutex
52
+
53
+ // acceptCh is used to pass ready streams to the client
54
+ acceptCh chan *Stream
55
+
56
+ // sendCh is used to mark a stream as ready to send,
57
+ // or to send a header out directly.
58
+ sendCh chan sendReady
59
+
60
+ // shutdown is used to safely close a session
61
+ shutdown bool
62
+ shutdownErr error
63
+ shutdownCh chan struct{}
64
+ shutdownLock sync.Mutex
65
+}
66
+
67
+// sendReady is used to either mark a stream as ready
68
+// or to directly send a header
69
+type sendReady struct {
70
+ Hdr []byte
71
+ Body io.Reader
72
+ Err chan error
73
+}
74
+
75
+// newSession is used to construct a new session
76
+func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session {
77
+ s := &Session{
78
+ config: config,
79
+ logger: log.New(config.LogOutput, "", log.LstdFlags),
80
+ conn: conn,
81
+ bufRead: bufio.NewReader(conn),
82
+ pings: make(map[uint32]chan struct{}),
83
+ streams: make(map[uint32]*Stream),
84
+ acceptCh: make(chan *Stream, config.AcceptBacklog),
85
+ sendCh: make(chan sendReady, 64),
86
+ shutdownCh: make(chan struct{}),
87
+ }
88
+ if client {
89
+ s.nextStreamID = 1
90
+ } else {
91
+ s.nextStreamID = 2
92
+ }
93
+ go s.recv()
94
+ go s.send()
95
+ if config.EnableKeepAlive {
96
+ go s.keepalive()
97
+ }
98
+ return s
99
+}
100
+
101
+// IsClosed does a safe check to see if we have shutdown
102
+func (s *Session) IsClosed() bool {
103
+ select {
104
+ case <-s.shutdownCh:
105
+ return true
106
+ default:
107
+ return false
108
+ }
109
+}
110
+
111
+// Open is used to create a new stream as a net.Conn
112
+func (s *Session) Open() (net.Conn, error) {
113
+ return s.OpenStream()
114
+}
115
+
116
+// OpenStream is used to create a new stream
117
+func (s *Session) OpenStream() (*Stream, error) {
118
+ if s.IsClosed() {
119
+ return nil, ErrSessionShutdown
120
+ }
121
+ if atomic.LoadInt32(&s.remoteGoAway) == 1 {
122
+ return nil, ErrRemoteGoAway
123
+ }
124
+
125
+GET_ID:
126
+ // Get and ID, and check for stream exhaustion
127
+ id := atomic.LoadUint32(&s.nextStreamID)
128
+ if id >= math.MaxUint32-1 {
129
+ return nil, ErrStreamsExhausted
130
+ }
131
+ if !atomic.CompareAndSwapUint32(&s.nextStreamID, id, id+2) {
132
+ goto GET_ID
133
+ }
134
+
135
+ // Register the stream
136
+ stream := newStream(s, id, streamInit)
137
+ s.streamLock.Lock()
138
+ s.streams[id] = stream
139
+ s.streamLock.Unlock()
140
+
141
+ // Send the window update to create
142
+ return stream, stream.sendWindowUpdate()
143
+}
144
+
145
+// Accept is used to block until the next available stream
146
+// is ready to be accepted.
147
+func (s *Session) Accept() (net.Conn, error) {
148
+ return s.AcceptStream()
149
+}
150
+
151
+// AcceptStream is used to block until the next available stream
152
+// is ready to be accepted.
153
+func (s *Session) AcceptStream() (*Stream, error) {
154
+ select {
155
+ case stream := <-s.acceptCh:
156
+ return stream, stream.sendWindowUpdate()
157
+ case <-s.shutdownCh:
158
+ return nil, s.shutdownErr
159
+ }
160
+}
161
+
162
+// Close is used to close the session and all streams.
163
+// Attempts to send a GoAway before closing the connection.
164
+func (s *Session) Close() error {
165
+ s.shutdownLock.Lock()
166
+ defer s.shutdownLock.Unlock()
167
+
168
+ if s.shutdown {
169
+ return nil
170
+ }
171
+ s.shutdown = true
172
+ if s.shutdownErr == nil {
173
+ s.shutdownErr = ErrSessionShutdown
174
+ }
175
+ close(s.shutdownCh)
176
+ s.conn.Close()
177
+
178
+ s.streamLock.Lock()
179
+ defer s.streamLock.Unlock()
180
+ for _, stream := range s.streams {
181
+ stream.forceClose()
182
+ }
183
+ return nil
184
+}
185
+
186
+// exitErr is used to handle an error that is causing the
187
+// session to terminate.
188
+func (s *Session) exitErr(err error) {
189
+ s.shutdownLock.Lock()
190
+ if s.shutdownErr == nil {
191
+ s.shutdownErr = err
192
+ }
193
+ s.shutdownLock.Unlock()
194
+ s.Close()
195
+}
196
+
197
+// GoAway can be used to prevent accepting further
198
+// connections. It does not close the underlying conn.
199
+func (s *Session) GoAway() error {
200
+ return s.waitForSend(s.goAway(goAwayNormal), nil)
201
+}
202
+
203
+// goAway is used to send a goAway message
204
+func (s *Session) goAway(reason uint32) header {
205
+ atomic.SwapInt32(&s.localGoAway, 1)
206
+ hdr := header(make([]byte, headerSize))
207
+ hdr.encode(typeGoAway, 0, 0, reason)
208
+ return hdr
209
+}
210
+
211
+// Ping is used to measure the RTT response time
212
+func (s *Session) Ping() (time.Duration, error) {
213
+ // Get a channel for the ping
214
+ ch := make(chan struct{})
215
+
216
+ // Get a new ping id, mark as pending
217
+ s.pingLock.Lock()
218
+ id := s.pingID
219
+ s.pingID++
220
+ s.pings[id] = ch
221
+ s.pingLock.Unlock()
222
+
223
+ // Send the ping request
224
+ hdr := header(make([]byte, headerSize))
225
+ hdr.encode(typePing, flagSYN, 0, id)
226
+ if err := s.waitForSend(hdr, nil); err != nil {
227
+ return 0, err
228
+ }
229
+
230
+ // Wait for a response
231
+ start := time.Now()
232
+ select {
233
+ case <-ch:
234
+ case <-s.shutdownCh:
235
+ return 0, ErrSessionShutdown
236
+ }
237
+
238
+ // Compute the RTT
239
+ return time.Now().Sub(start), nil
240
+}
241
+
242
+// keepalive is a long running goroutine that periodically does
243
+// a ping to keep the connection alive.
244
+func (s *Session) keepalive() {
245
+ for {
246
+ select {
247
+ case <-time.After(s.config.KeepAliveInterval):
248
+ s.Ping()
249
+ case <-s.shutdownCh:
250
+ return
251
+ }
252
+ }
253
+}
254
+
255
+// waitForSendErr waits to send a header, checking for a potential shutdown
256
+func (s *Session) waitForSend(hdr header, body io.Reader) error {
257
+ errCh := make(chan error, 1)
258
+ return s.waitForSendErr(hdr, body, errCh)
259
+}
260
+
261
+// waitForSendErr waits to send a header, checking for a potential shutdown
262
+func (s *Session) waitForSendErr(hdr header, body io.Reader, errCh chan error) error {
263
+ ready := sendReady{Hdr: hdr, Body: body, Err: errCh}
264
+ select {
265
+ case s.sendCh <- ready:
266
+ case <-s.shutdownCh:
267
+ return ErrSessionShutdown
268
+ }
269
+ select {
270
+ case err := <-errCh:
271
+ return err
272
+ case <-s.shutdownCh:
273
+ return ErrSessionShutdown
274
+ }
275
+}
276
+
277
+// sendNoWait does a send without waiting
278
+func (s *Session) sendNoWait(hdr header) error {
279
+ select {
280
+ case s.sendCh <- sendReady{Hdr: hdr}:
281
+ return nil
282
+ case <-s.shutdownCh:
283
+ return ErrSessionShutdown
284
+ }
285
+}
286
+
287
+// send is a long running goroutine that sends data
288
+func (s *Session) send() {
289
+ for {
290
+ select {
291
+ case ready := <-s.sendCh:
292
+ // Send a header if ready
293
+ if ready.Hdr != nil {
294
+ sent := 0
295
+ for sent < len(ready.Hdr) {
296
+ n, err := s.conn.Write(ready.Hdr[sent:])
297
+ if err != nil {
298
+ s.logger.Printf("[ERR] yamux: Failed to write header: %v", err)
299
+ asyncSendErr(ready.Err, err)
300
+ s.exitErr(err)
301
+ return
302
+ }
303
+ sent += n
304
+ }
305
+ }
306
+
307
+ // Send data from a body if given
308
+ if ready.Body != nil {
309
+ _, err := io.Copy(s.conn, ready.Body)
310
+ if err != nil {
311
+ s.logger.Printf("[ERR] yamux: Failed to write body: %v", err)
312
+ asyncSendErr(ready.Err, err)
313
+ s.exitErr(err)
314
+ return
315
+ }
316
+ }
317
+
318
+ // No error, successful send
319
+ asyncSendErr(ready.Err, nil)
320
+ case <-s.shutdownCh:
321
+ return
322
+ }
323
+ }
324
+}
325
+
326
+// recv is a long running goroutine that accepts new data
327
+func (s *Session) recv() {
328
+ hdr := header(make([]byte, headerSize))
329
+ var handler func(header) error
330
+ for {
331
+ // Read the header
332
+ if _, err := io.ReadFull(s.bufRead, hdr); err != nil {
333
+ if err != io.EOF && !strings.Contains(err.Error(), "closed") && !strings.Contains(err.Error(), "reset by peer") {
334
+ s.logger.Printf("[ERR] yamux: Failed to read header: %v", err)
335
+ }
336
+ s.exitErr(err)
337
+ return
338
+ }
339
+
340
+ // Verify the version
341
+ if hdr.Version() != protoVersion {
342
+ s.logger.Printf("[ERR] yamux: Invalid protocol version: %d", hdr.Version())
343
+ s.exitErr(ErrInvalidVersion)
344
+ return
345
+ }
346
+
347
+ // Switch on the type
348
+ switch hdr.MsgType() {
349
+ case typeData:
350
+ handler = s.handleStreamMessage
351
+ case typeWindowUpdate:
352
+ handler = s.handleStreamMessage
353
+ case typeGoAway:
354
+ handler = s.handleGoAway
355
+ case typePing:
356
+ handler = s.handlePing
357
+ default:
358
+ s.exitErr(ErrInvalidMsgType)
359
+ return
360
+ }
361
+
362
+ // Invoke the handler
363
+ if err := handler(hdr); err != nil {
364
+ s.exitErr(err)
365
+ return
366
+ }
367
+ }
368
+}
369
+
370
+// handleStreamMessage handles either a data or window update frame
371
+func (s *Session) handleStreamMessage(hdr header) error {
372
+ // Check for a new stream creation
373
+ id := hdr.StreamID()
374
+ flags := hdr.Flags()
375
+ if flags&flagSYN == flagSYN {
376
+ if err := s.incomingStream(id); err != nil {
377
+ return err
378
+ }
379
+ }
380
+
381
+ // Get the stream
382
+ s.streamLock.Lock()
383
+ stream := s.streams[id]
384
+ s.streamLock.Unlock()
385
+
386
+ // If we do not have a stream, likely we sent a RST
387
+ if stream == nil {
388
+ // Drain any data on the wire
389
+ if hdr.MsgType() == typeData && hdr.Length() > 0 {
390
+ s.logger.Printf("[WARN] yamux: Discarding data for stream: %d", id)
391
+ if _, err := io.CopyN(ioutil.Discard, s.bufRead, int64(hdr.Length())); err != nil {
392
+ s.logger.Printf("[ERR] yamux: Failed to discard data: %v", err)
393
+ return nil
394
+ }
395
+ } else {
396
+ s.logger.Printf("[WARN] yamux: frame for missing stream: %v", hdr)
397
+ }
398
+ return nil
399
+ }
400
+
401
+ // Check if this is a window update
402
+ if hdr.MsgType() == typeWindowUpdate {
403
+ if err := stream.incrSendWindow(hdr, flags); err != nil {
404
+ s.sendNoWait(s.goAway(goAwayProtoErr))
405
+ return err
406
+ }
407
+ return nil
408
+ }
409
+
410
+ // Read the new data
411
+ if err := stream.readData(hdr, flags, s.bufRead); err != nil {
412
+ s.sendNoWait(s.goAway(goAwayProtoErr))
413
+ return err
414
+ }
415
+ return nil
416
+}
417
+
418
+// handlePing is invokde for a typePing frame
419
+func (s *Session) handlePing(hdr header) error {
420
+ flags := hdr.Flags()
421
+ pingID := hdr.Length()
422
+
423
+ // Check if this is a query, respond back
424
+ if flags&flagSYN == flagSYN {
425
+ hdr := header(make([]byte, headerSize))
426
+ hdr.encode(typePing, flagACK, 0, pingID)
427
+ s.sendNoWait(hdr)
428
+ return nil
429
+ }
430
+
431
+ // Handle a response
432
+ s.pingLock.Lock()
433
+ ch := s.pings[pingID]
434
+ if ch != nil {
435
+ delete(s.pings, pingID)
436
+ close(ch)
437
+ }
438
+ s.pingLock.Unlock()
439
+ return nil
440
+}
441
+
442
+// handleGoAway is invokde for a typeGoAway frame
443
+func (s *Session) handleGoAway(hdr header) error {
444
+ code := hdr.Length()
445
+ switch code {
446
+ case goAwayNormal:
447
+ atomic.SwapInt32(&s.remoteGoAway, 1)
448
+ case goAwayProtoErr:
449
+ s.logger.Printf("[ERR] yamux: received protocol error go away")
450
+ return fmt.Errorf("yamux protocol error")
451
+ case goAwayInternalErr:
452
+ s.logger.Printf("[ERR] yamux: received internal error go away")
453
+ return fmt.Errorf("remote yamux internal error")
454
+ default:
455
+ s.logger.Printf("[ERR] yamux: received unexpected go away")
456
+ return fmt.Errorf("unexpected go away received")
457
+ }
458
+ return nil
459
+}
460
+
461
+// incomingStream is used to create a new incoming stream
462
+func (s *Session) incomingStream(id uint32) error {
463
+ // Reject immediately if we are doing a go away
464
+ if atomic.LoadInt32(&s.localGoAway) == 1 {
465
+ hdr := header(make([]byte, headerSize))
466
+ hdr.encode(typeWindowUpdate, flagRST, id, 0)
467
+ return s.sendNoWait(hdr)
468
+ }
469
+
470
+ // Allocate a new stream
471
+ stream := newStream(s, id, streamSYNReceived)
472
+
473
+ s.streamLock.Lock()
474
+ defer s.streamLock.Unlock()
475
+
476
+ // Check if stream already exists
477
+ if _, ok := s.streams[id]; ok {
478
+ s.logger.Printf("[ERR] yamux: duplicate stream declared")
479
+ s.sendNoWait(s.goAway(goAwayProtoErr))
480
+ return ErrDuplicateStream
481
+ }
482
+
483
+ // Register the stream
484
+ s.streams[id] = stream
485
+
486
+ // Check if we've exceeded the backlog
487
+ select {
488
+ case s.acceptCh <- stream:
489
+ return nil
490
+ default:
491
+ // Backlog exceeded! RST the stream
492
+ s.logger.Printf("[WARN] yamux: backlog exceeded, forcing connection reset")
493
+ delete(s.streams, id)
494
+ stream.sendHdr.encode(typeWindowUpdate, flagRST, id, 0)
495
+ return s.sendNoWait(stream.sendHdr)
496
+ }
497
+}
498
+
499
+// closeStream is used to close a stream once both sides have
500
+// issued a close.
501
+func (s *Session) closeStream(id uint32) {
502
+ s.streamLock.Lock()
503
+ delete(s.streams, id)
504
+ s.streamLock.Unlock()
505
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/session_test.go
new
+729
@@ -0,0 +1,729 @@
1
+package yamux
2
+
3
+import (
4
+ "bytes"
5
+ "fmt"
6
+ "io"
7
+ "io/ioutil"
8
+ "runtime"
9
+ "sync"
10
+ "testing"
11
+ "time"
12
+)
13
+
14
+type pipeConn struct {
15
+ reader *io.PipeReader
16
+ writer *io.PipeWriter
17
+}
18
+
19
+func (p *pipeConn) Read(b []byte) (int, error) {
20
+ return p.reader.Read(b)
21
+}
22
+
23
+func (p *pipeConn) Write(b []byte) (int, error) {
24
+ return p.writer.Write(b)
25
+}
26
+
27
+func (p *pipeConn) Close() error {
28
+ p.reader.Close()
29
+ return p.writer.Close()
30
+}
31
+
32
+func testConn() (io.ReadWriteCloser, io.ReadWriteCloser) {
33
+ read1, write1 := io.Pipe()
34
+ read2, write2 := io.Pipe()
35
+ return &pipeConn{read1, write2}, &pipeConn{read2, write1}
36
+}
37
+
38
+func testClientServer() (*Session, *Session) {
39
+ conf := DefaultConfig()
40
+ conf.AcceptBacklog = 64
41
+ conf.KeepAliveInterval = 100 * time.Millisecond
42
+ return testClientServerConfig(conf)
43
+}
44
+
45
+func testClientServerConfig(conf *Config) (*Session, *Session) {
46
+ conn1, conn2 := testConn()
47
+ client, _ := Client(conn1, conf)
48
+ server, _ := Server(conn2, conf)
49
+ return client, server
50
+}
51
+
52
+func TestPing(t *testing.T) {
53
+ client, server := testClientServer()
54
+ defer client.Close()
55
+ defer server.Close()
56
+
57
+ rtt, err := client.Ping()
58
+ if err != nil {
59
+ t.Fatalf("err: %v", err)
60
+ }
61
+ if rtt == 0 {
62
+ t.Fatalf("bad: %v", rtt)
63
+ }
64
+
65
+ rtt, err = server.Ping()
66
+ if err != nil {
67
+ t.Fatalf("err: %v", err)
68
+ }
69
+ if rtt == 0 {
70
+ t.Fatalf("bad: %v", rtt)
71
+ }
72
+}
73
+
74
+func TestAccept(t *testing.T) {
75
+ client, server := testClientServer()
76
+ defer client.Close()
77
+ defer server.Close()
78
+
79
+ wg := &sync.WaitGroup{}
80
+ wg.Add(4)
81
+
82
+ go func() {
83
+ defer wg.Done()
84
+ stream, err := server.AcceptStream()
85
+ if err != nil {
86
+ t.Fatalf("err: %v", err)
87
+ }
88
+ if id := stream.StreamID(); id != 1 {
89
+ t.Fatalf("bad: %v", id)
90
+ }
91
+ if err := stream.Close(); err != nil {
92
+ t.Fatalf("err: %v", err)
93
+ }
94
+ }()
95
+
96
+ go func() {
97
+ defer wg.Done()
98
+ stream, err := client.AcceptStream()
99
+ if err != nil {
100
+ t.Fatalf("err: %v", err)
101
+ }
102
+ if id := stream.StreamID(); id != 2 {
103
+ t.Fatalf("bad: %v", id)
104
+ }
105
+ if err := stream.Close(); err != nil {
106
+ t.Fatalf("err: %v", err)
107
+ }
108
+ }()
109
+
110
+ go func() {
111
+ defer wg.Done()
112
+ stream, err := server.OpenStream()
113
+ if err != nil {
114
+ t.Fatalf("err: %v", err)
115
+ }
116
+ if id := stream.StreamID(); id != 2 {
117
+ t.Fatalf("bad: %v", id)
118
+ }
119
+ if err := stream.Close(); err != nil {
120
+ t.Fatalf("err: %v", err)
121
+ }
122
+ }()
123
+
124
+ go func() {
125
+ defer wg.Done()
126
+ stream, err := client.OpenStream()
127
+ if err != nil {
128
+ t.Fatalf("err: %v", err)
129
+ }
130
+ if id := stream.StreamID(); id != 1 {
131
+ t.Fatalf("bad: %v", id)
132
+ }
133
+ if err := stream.Close(); err != nil {
134
+ t.Fatalf("err: %v", err)
135
+ }
136
+ }()
137
+
138
+ doneCh := make(chan struct{})
139
+ go func() {
140
+ wg.Wait()
141
+ close(doneCh)
142
+ }()
143
+
144
+ select {
145
+ case <-doneCh:
146
+ case <-time.After(time.Second):
147
+ panic("timeout")
148
+ }
149
+}
150
+
151
+func TestSendData_Small(t *testing.T) {
152
+ client, server := testClientServer()
153
+ defer client.Close()
154
+ defer server.Close()
155
+
156
+ wg := &sync.WaitGroup{}
157
+ wg.Add(2)
158
+
159
+ go func() {
160
+ defer wg.Done()
161
+ stream, err := server.AcceptStream()
162
+ if err != nil {
163
+ t.Fatalf("err: %v", err)
164
+ }
165
+
166
+ buf := make([]byte, 4)
167
+ for i := 0; i < 1000; i++ {
168
+ n, err := stream.Read(buf)
169
+ if err != nil {
170
+ t.Fatalf("err: %v", err)
171
+ }
172
+ if n != 4 {
173
+ t.Fatalf("short read: %d", n)
174
+ }
175
+ if string(buf) != "test" {
176
+ t.Fatalf("bad: %s", buf)
177
+ }
178
+ }
179
+
180
+ if err := stream.Close(); err != nil {
181
+ t.Fatalf("err: %v", err)
182
+ }
183
+ }()
184
+
185
+ go func() {
186
+ defer wg.Done()
187
+ stream, err := client.Open()
188
+ if err != nil {
189
+ t.Fatalf("err: %v", err)
190
+ }
191
+
192
+ for i := 0; i < 1000; i++ {
193
+ n, err := stream.Write([]byte("test"))
194
+ if err != nil {
195
+ t.Fatalf("err: %v", err)
196
+ }
197
+ if n != 4 {
198
+ t.Fatalf("short write %d", n)
199
+ }
200
+ }
201
+
202
+ if err := stream.Close(); err != nil {
203
+ t.Fatalf("err: %v", err)
204
+ }
205
+ }()
206
+
207
+ doneCh := make(chan struct{})
208
+ go func() {
209
+ wg.Wait()
210
+ close(doneCh)
211
+ }()
212
+ select {
213
+ case <-doneCh:
214
+ case <-time.After(time.Second):
215
+ panic("timeout")
216
+ }
217
+}
218
+
219
+func TestSendData_Large(t *testing.T) {
220
+ client, server := testClientServer()
221
+ defer client.Close()
222
+ defer server.Close()
223
+
224
+ data := make([]byte, 512*1024)
225
+ for idx := range data {
226
+ data[idx] = byte(idx % 256)
227
+ }
228
+
229
+ wg := &sync.WaitGroup{}
230
+ wg.Add(2)
231
+
232
+ go func() {
233
+ defer wg.Done()
234
+ stream, err := server.AcceptStream()
235
+ if err != nil {
236
+ t.Fatalf("err: %v", err)
237
+ }
238
+
239
+ buf := make([]byte, 4*1024)
240
+ for i := 0; i < 128; i++ {
241
+ n, err := stream.Read(buf)
242
+ if err != nil {
243
+ t.Fatalf("err: %v", err)
244
+ }
245
+ if n != 4*1024 {
246
+ t.Fatalf("short read: %d", n)
247
+ }
248
+ for idx := range buf {
249
+ if buf[idx] != byte(idx%256) {
250
+ t.Fatalf("bad: %v %v %v", i, idx, buf[idx])
251
+ }
252
+ }
253
+ }
254
+
255
+ if err := stream.Close(); err != nil {
256
+ t.Fatalf("err: %v", err)
257
+ }
258
+ }()
259
+
260
+ go func() {
261
+ defer wg.Done()
262
+ stream, err := client.Open()
263
+ if err != nil {
264
+ t.Fatalf("err: %v", err)
265
+ }
266
+
267
+ n, err := stream.Write(data)
268
+ if err != nil {
269
+ t.Fatalf("err: %v", err)
270
+ }
271
+ if n != len(data) {
272
+ t.Fatalf("short write %d", n)
273
+ }
274
+
275
+ if err := stream.Close(); err != nil {
276
+ t.Fatalf("err: %v", err)
277
+ }
278
+ }()
279
+
280
+ doneCh := make(chan struct{})
281
+ go func() {
282
+ wg.Wait()
283
+ close(doneCh)
284
+ }()
285
+ select {
286
+ case <-doneCh:
287
+ case <-time.After(time.Second):
288
+ panic("timeout")
289
+ }
290
+}
291
+
292
+func TestGoAway(t *testing.T) {
293
+ client, server := testClientServer()
294
+ defer client.Close()
295
+ defer server.Close()
296
+
297
+ if err := server.GoAway(); err != nil {
298
+ t.Fatalf("err: %v", err)
299
+ }
300
+
301
+ _, err := client.Open()
302
+ if err != ErrRemoteGoAway {
303
+ t.Fatalf("err: %v", err)
304
+ }
305
+}
306
+
307
+func TestManyStreams(t *testing.T) {
308
+ client, server := testClientServer()
309
+ defer client.Close()
310
+ defer server.Close()
311
+
312
+ wg := &sync.WaitGroup{}
313
+
314
+ acceptor := func(i int) {
315
+ defer wg.Done()
316
+ stream, err := server.AcceptStream()
317
+ if err != nil {
318
+ t.Fatalf("err: %v", err)
319
+ }
320
+ defer stream.Close()
321
+
322
+ buf := make([]byte, 512)
323
+ for {
324
+ n, err := stream.Read(buf)
325
+ if err == io.EOF {
326
+ return
327
+ }
328
+ if err != nil {
329
+ t.Fatalf("err: %v", err)
330
+ }
331
+ if n == 0 {
332
+ t.Fatalf("err: %v", err)
333
+ }
334
+ }
335
+ }
336
+ sender := func(i int) {
337
+ defer wg.Done()
338
+ stream, err := client.Open()
339
+ if err != nil {
340
+ t.Fatalf("err: %v", err)
341
+ }
342
+ defer stream.Close()
343
+
344
+ msg := fmt.Sprintf("%08d", i)
345
+ for i := 0; i < 1000; i++ {
346
+ n, err := stream.Write([]byte(msg))
347
+ if err != nil {
348
+ t.Fatalf("err: %v", err)
349
+ }
350
+ if n != len(msg) {
351
+ t.Fatalf("short write %d", n)
352
+ }
353
+ }
354
+ }
355
+
356
+ for i := 0; i < 50; i++ {
357
+ wg.Add(2)
358
+ go acceptor(i)
359
+ go sender(i)
360
+ }
361
+
362
+ wg.Wait()
363
+}
364
+
365
+func TestManyStreams_PingPong(t *testing.T) {
366
+ client, server := testClientServer()
367
+ defer client.Close()
368
+ defer server.Close()
369
+
370
+ wg := &sync.WaitGroup{}
371
+
372
+ ping := []byte("ping")
373
+ pong := []byte("pong")
374
+
375
+ acceptor := func(i int) {
376
+ defer wg.Done()
377
+ stream, err := server.AcceptStream()
378
+ if err != nil {
379
+ t.Fatalf("err: %v", err)
380
+ }
381
+ defer stream.Close()
382
+
383
+ buf := make([]byte, 4)
384
+ for {
385
+ n, err := stream.Read(buf)
386
+ if err == io.EOF {
387
+ return
388
+ }
389
+ if err != nil {
390
+ t.Fatalf("err: %v", err)
391
+ }
392
+ if n != 4 {
393
+ t.Fatalf("err: %v", err)
394
+ }
395
+ if !bytes.Equal(buf, ping) {
396
+ t.Fatalf("bad: %s", buf)
397
+ }
398
+ n, err = stream.Write(pong)
399
+ if err != nil {
400
+ t.Fatalf("err: %v", err)
401
+ }
402
+ if n != 4 {
403
+ t.Fatalf("err: %v", err)
404
+ }
405
+ }
406
+ }
407
+ sender := func(i int) {
408
+ defer wg.Done()
409
+ stream, err := client.Open()
410
+ if err != nil {
411
+ t.Fatalf("err: %v", err)
412
+ }
413
+ defer stream.Close()
414
+
415
+ buf := make([]byte, 4)
416
+ for i := 0; i < 1000; i++ {
417
+ n, err := stream.Write(ping)
418
+ if err != nil {
419
+ t.Fatalf("err: %v", err)
420
+ }
421
+ if n != 4 {
422
+ t.Fatalf("short write %d", n)
423
+ }
424
+
425
+ n, err = stream.Read(buf)
426
+ if err != nil {
427
+ t.Fatalf("err: %v", err)
428
+ }
429
+ if n != 4 {
430
+ t.Fatalf("err: %v", err)
431
+ }
432
+ if !bytes.Equal(buf, pong) {
433
+ t.Fatalf("bad: %s", buf)
434
+ }
435
+ }
436
+ }
437
+
438
+ for i := 0; i < 50; i++ {
439
+ wg.Add(2)
440
+ go acceptor(i)
441
+ go sender(i)
442
+ }
443
+
444
+ wg.Wait()
445
+}
446
+
447
+func TestHalfClose(t *testing.T) {
448
+ client, server := testClientServer()
449
+ defer client.Close()
450
+ defer server.Close()
451
+
452
+ stream, err := client.Open()
453
+ if err != nil {
454
+ t.Fatalf("err: %v", err)
455
+ }
456
+ if _, err := stream.Write([]byte("a")); err != nil {
457
+ t.Fatalf("err: %v", err)
458
+ }
459
+
460
+ stream2, err := server.Accept()
461
+ if err != nil {
462
+ t.Fatalf("err: %v", err)
463
+ }
464
+ stream2.Close() // Half close
465
+
466
+ buf := make([]byte, 4)
467
+ n, err := stream2.Read(buf)
468
+ if err != nil {
469
+ t.Fatalf("err: %v", err)
470
+ }
471
+ if n != 1 {
472
+ t.Fatalf("bad: %v", n)
473
+ }
474
+
475
+ // Send more
476
+ if _, err := stream.Write([]byte("bcd")); err != nil {
477
+ t.Fatalf("err: %v", err)
478
+ }
479
+ stream.Close()
480
+
481
+ // Read after close
482
+ n, err = stream2.Read(buf)
483
+ if err != nil {
484
+ t.Fatalf("err: %v", err)
485
+ }
486
+ if n != 3 {
487
+ t.Fatalf("bad: %v", n)
488
+ }
489
+
490
+ // EOF after close
491
+ n, err = stream2.Read(buf)
492
+ if err != io.EOF {
493
+ t.Fatalf("err: %v", err)
494
+ }
495
+ if n != 0 {
496
+ t.Fatalf("bad: %v", n)
497
+ }
498
+}
499
+
500
+func TestReadDeadline(t *testing.T) {
501
+ client, server := testClientServer()
502
+ defer client.Close()
503
+ defer server.Close()
504
+
505
+ stream, err := client.Open()
506
+ if err != nil {
507
+ t.Fatalf("err: %v", err)
508
+ }
509
+ defer stream.Close()
510
+
511
+ stream2, err := server.Accept()
512
+ if err != nil {
513
+ t.Fatalf("err: %v", err)
514
+ }
515
+ defer stream2.Close()
516
+
517
+ if err := stream.SetReadDeadline(time.Now().Add(5 * time.Millisecond)); err != nil {
518
+ t.Fatalf("err: %v", err)
519
+ }
520
+
521
+ buf := make([]byte, 4)
522
+ if _, err := stream.Read(buf); err != ErrTimeout {
523
+ t.Fatalf("err: %v", err)
524
+ }
525
+}
526
+
527
+func TestWriteDeadline(t *testing.T) {
528
+ client, server := testClientServer()
529
+ defer client.Close()
530
+ defer server.Close()
531
+
532
+ stream, err := client.Open()
533
+ if err != nil {
534
+ t.Fatalf("err: %v", err)
535
+ }
536
+ defer stream.Close()
537
+
538
+ stream2, err := server.Accept()
539
+ if err != nil {
540
+ t.Fatalf("err: %v", err)
541
+ }
542
+ defer stream2.Close()
543
+
544
+ if err := stream.SetWriteDeadline(time.Now().Add(50 * time.Millisecond)); err != nil {
545
+ t.Fatalf("err: %v", err)
546
+ }
547
+
548
+ buf := make([]byte, 512)
549
+ for i := 0; i < int(initialStreamWindow); i++ {
550
+ _, err := stream.Write(buf)
551
+ if err != nil && err == ErrTimeout {
552
+ return
553
+ } else if err != nil {
554
+ t.Fatalf("err: %v", err)
555
+ }
556
+ }
557
+ t.Fatalf("Expected timeout")
558
+}
559
+
560
+func TestBacklogExceeded(t *testing.T) {
561
+ client, server := testClientServer()
562
+ defer client.Close()
563
+ defer server.Close()
564
+
565
+ // Fill the backlog
566
+ max := client.config.AcceptBacklog
567
+ for i := 0; i < max; i++ {
568
+ stream, err := client.Open()
569
+ if err != nil {
570
+ t.Fatalf("err: %v", err)
571
+ }
572
+ defer stream.Close()
573
+
574
+ if _, err := stream.Write([]byte("foo")); err != nil {
575
+ t.Fatalf("err: %v", err)
576
+ }
577
+ }
578
+
579
+ // Exceed the backlog!
580
+ stream, err := client.Open()
581
+ if err != nil {
582
+ t.Fatalf("err: %v", err)
583
+ }
584
+ defer stream.Close()
585
+
586
+ if _, err := stream.Write([]byte("foo")); err != nil {
587
+ t.Fatalf("err: %v", err)
588
+ }
589
+
590
+ buf := make([]byte, 4)
591
+ stream.SetReadDeadline(time.Now().Add(50 * time.Millisecond))
592
+ if _, err := stream.Read(buf); err != ErrConnectionReset {
593
+ t.Fatalf("err: %v", err)
594
+ }
595
+}
596
+
597
+func TestKeepAlive(t *testing.T) {
598
+ client, server := testClientServer()
599
+ defer client.Close()
600
+ defer server.Close()
601
+
602
+ time.Sleep(200 * time.Millisecond)
603
+
604
+ // Ping value should increase
605
+ client.pingLock.Lock()
606
+ defer client.pingLock.Unlock()
607
+ if client.pingID == 0 {
608
+ t.Fatalf("should ping")
609
+ }
610
+
611
+ server.pingLock.Lock()
612
+ defer server.pingLock.Unlock()
613
+ if server.pingID == 0 {
614
+ t.Fatalf("should ping")
615
+ }
616
+}
617
+
618
+func TestLargeWindow(t *testing.T) {
619
+ conf := DefaultConfig()
620
+ conf.MaxStreamWindowSize *= 2
621
+
622
+ client, server := testClientServerConfig(conf)
623
+ defer client.Close()
624
+ defer server.Close()
625
+
626
+ stream, err := client.Open()
627
+ if err != nil {
628
+ t.Fatalf("err: %v", err)
629
+ }
630
+ defer stream.Close()
631
+
632
+ stream2, err := server.Accept()
633
+ if err != nil {
634
+ t.Fatalf("err: %v", err)
635
+ }
636
+ defer stream2.Close()
637
+
638
+ stream.SetWriteDeadline(time.Now().Add(10 * time.Millisecond))
639
+ buf := make([]byte, conf.MaxStreamWindowSize)
640
+ n, err := stream.Write(buf)
641
+ if err != nil {
642
+ t.Fatalf("err: %v", err)
643
+ }
644
+ if n != len(buf) {
645
+ t.Fatalf("short write: %d", n)
646
+ }
647
+}
648
+
649
+type UnlimitedReader struct{}
650
+
651
+func (u *UnlimitedReader) Read(p []byte) (int, error) {
652
+ runtime.Gosched()
653
+ return len(p), nil
654
+}
655
+
656
+func TestSendData_VeryLarge(t *testing.T) {
657
+ client, server := testClientServer()
658
+ defer client.Close()
659
+ defer server.Close()
660
+
661
+ var n int64 = 1 * 1024 * 1024 * 1024
662
+ var workers int = 16
663
+
664
+ wg := &sync.WaitGroup{}
665
+ wg.Add(workers * 2)
666
+
667
+ for i := 0; i < workers; i++ {
668
+ go func() {
669
+ defer wg.Done()
670
+ stream, err := server.AcceptStream()
671
+ if err != nil {
672
+ t.Fatalf("err: %v", err)
673
+ }
674
+ defer stream.Close()
675
+
676
+ buf := make([]byte, 4)
677
+ _, err = stream.Read(buf)
678
+ if err != nil {
679
+ t.Fatalf("err: %v", err)
680
+ }
681
+ if !bytes.Equal(buf, []byte{0, 1, 2, 3}) {
682
+ t.Fatalf("bad header")
683
+ }
684
+
685
+ recv, err := io.Copy(ioutil.Discard, stream)
686
+ if err != nil {
687
+ t.Fatalf("err: %v", err)
688
+ }
689
+ if recv != n {
690
+ t.Fatalf("bad: %v", recv)
691
+ }
692
+ }()
693
+ }
694
+ for i := 0; i < workers; i++ {
695
+ go func() {
696
+ defer wg.Done()
697
+ stream, err := client.Open()
698
+ if err != nil {
699
+ t.Fatalf("err: %v", err)
700
+ }
701
+ defer stream.Close()
702
+
703
+ _, err = stream.Write([]byte{0, 1, 2, 3})
704
+ if err != nil {
705
+ t.Fatalf("err: %v", err)
706
+ }
707
+
708
+ unlimited := &UnlimitedReader{}
709
+ sent, err := io.Copy(stream, io.LimitReader(unlimited, n))
710
+ if err != nil {
711
+ t.Fatalf("err: %v", err)
712
+ }
713
+ if sent != n {
714
+ t.Fatalf("bad: %v", sent)
715
+ }
716
+ }()
717
+ }
718
+
719
+ doneCh := make(chan struct{})
720
+ go func() {
721
+ wg.Wait()
722
+ close(doneCh)
723
+ }()
724
+ select {
725
+ case <-doneCh:
726
+ case <-time.After(20 * time.Second):
727
+ panic("timeout")
728
+ }
729
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/spec.md
new
+141
@@ -0,0 +1,141 @@
1
+# Specification
2
+
3
+We use this document to detail the internal specification of Yamux.
4
+This is used both as a guide for implementing Yamux, but also for
5
+alternative interoperable libraries to be built.
6
+
7
+# Framing
8
+
9
+Yamux uses a streaming connection underneath, but imposes a message
10
+framing so that it can be shared between many logical streams. Each
11
+frame contains a header like:
12
+
13
+* Version (8 bits)
14
+* Type (8 bits)
15
+* Flags (16 bits)
16
+* StreamID (32 bits)
17
+* Length (32 bits)
18
+
19
+This means that each header has a 12 byte overhead.
20
+All fields are encoded in network order (big endian).
21
+Each field is described below:
22
+
23
+## Version Field
24
+
25
+The version field is used for future backwards compatibily. At the
26
+current time, the field is always set to 0, to indicate the initial
27
+version.
28
+
29
+## Type Field
30
+
31
+The type field is used to switch the frame message type. The following
32
+message types are supported:
33
+
34
+* 0x0 Data - Used to transmit data. May transmit zero length payloads
35
+ depending on the flags.
36
+
37
+* 0x1 Window Update - Used to updated the senders receive window size.
38
+ This is used to implement per-session flow control.
39
+
40
+* 0x2 Ping - Used to measure RTT. It can also be used to heart-beat
41
+ and do keep-alives over TCP.
42
+
43
+* 0x3 Go Away - Used to close a session.
44
+
45
+## Flag Field
46
+
47
+The flags field is used to provide additional information related
48
+to the message type. The following flags are supported:
49
+
50
+* 0x1 SYN - Signals the start of a new stream. May be sent with a data or
51
+ window update message. Also sent with a ping to indicate outbound.
52
+
53
+* 0x2 ACK - Acknowledges the start of a new stream. May be sent with a data
54
+ or window update message. Also sent with a ping to indicate response.
55
+
56
+* 0x4 FIN - Performs a half-close of a stream. May be sent with a data
57
+ message or window update.
58
+
59
+* 0x8 RST - Reset a stream immediately. May be sent with a data or
60
+ window update message.
61
+
62
+## StreamID Field
63
+
64
+The StreamID field is used to identify the logical stream the frame
65
+is addressing. The client side should use odd ID's, and the server even.
66
+This prevents any collisions. Additionally, the 0 ID is reserved to represent
67
+the session.
68
+
69
+Both Ping and Go Away messages should always use the 0 StreamID.
70
+
71
+## Length Field
72
+
73
+The meaning of the length field depends on the message type:
74
+
75
+* Data - provides the length of bytes following the header
76
+* Window update - provides a delta update to the window size
77
+* Ping - Contains an opaque value, echoed back
78
+* Go Away - Contains an error code
79
+
80
+# Message Flow
81
+
82
+There is no explicit connection setup, as Yamux relies on an underlying
83
+transport to be provided. However, there is a distinction between client
84
+and server side of the connection.
85
+
86
+## Opening a stream
87
+
88
+To open a stream, an initial data or window update frame is sent
89
+with a new StreamID. The SYN flag should be set to signal a new stream.
90
+
91
+The receiver must then reply with either a data or window update frame
92
+with the StreamID along with the ACK flag to accept the stream or with
93
+the RST flag to reject the stream.
94
+
95
+Because we are relying on the reliable stream underneath, a connection
96
+can begin sending data once the SYN flag is sent. The corresponding
97
+ACK does not need to be received. This is particularly well suited
98
+for an RPC system where a client wants to open a stream and immediately
99
+fire a request without wiating for the RTT of the ACK.
100
+
101
+This does introduce the possibility of a connection being rejected
102
+after data has been sent already. This is a slight semantic difference
103
+from TCP, where the conection cannot be refused after it is opened.
104
+Clients should be prepared to handle this by checking for an error
105
+that indicates a RST was received.
106
+
107
+## Closing a stream
108
+
109
+To close a stream, either side sends a data or window update frame
110
+along with the FIN flag. This does a half-close indicating the sender
111
+will send no further data.
112
+
113
+Once both sides have closed the connection, the stream is closed.
114
+
115
+Alternatively, if an error occurs, the RST flag can be used to
116
+hard close a stream immediately.
117
+
118
+## Flow Control
119
+
120
+When Yamux is initially starts each stream with a 256KB window size.
121
+There is no window size for the session.
122
+
123
+To prevent the streams from stalling, window update frames should be
124
+sent regularly. Yamux can be configured to provide a larger limit for
125
+windows sizes. Both sides assume the initial 256KB window, but can
126
+immediately send a window update as part of the SYN/ACK indicating a
127
+larger window.
128
+
129
+Both sides should track the number of bytes sent in Data frames
130
+only, as only they are tracked as part of the window size.
131
+
132
+## Session termination
133
+
134
+When a session is being terminated, the Go Away message should
135
+be sent. The Length should be set to one of the following to
136
+provide an error code:
137
+
138
+* 0x0 Normal termination
139
+* 0x1 Protocol error
140
+* 0x2 Internal error
141
+
Godeps/_workspace/src/github.com/hashicorp/yamux/stream.go
new
+417
@@ -0,0 +1,417 @@
1
+package yamux
2
+
3
+import (
4
+ "bytes"
5
+ "io"
6
+ "sync"
7
+ "sync/atomic"
8
+ "time"
9
+)
10
+
11
+type streamState int
12
+
13
+const (
14
+ streamInit streamState = iota
15
+ streamSYNSent
16
+ streamSYNReceived
17
+ streamEstablished
18
+ streamLocalClose
19
+ streamRemoteClose
20
+ streamClosed
21
+ streamReset
22
+)
23
+
24
+// Stream is used to represent a logical stream
25
+// within a session.
26
+type Stream struct {
27
+ recvWindow uint32
28
+ sendWindow uint32
29
+
30
+ id uint32
31
+ session *Session
32
+
33
+ state streamState
34
+ stateLock sync.Mutex
35
+
36
+ recvBuf bytes.Buffer
37
+ recvLock sync.Mutex
38
+
39
+ controlHdr header
40
+ controlErr chan error
41
+ controlHdrLock sync.Mutex
42
+
43
+ sendHdr header
44
+ sendErr chan error
45
+ sendLock sync.Mutex
46
+
47
+ recvNotifyCh chan struct{}
48
+ sendNotifyCh chan struct{}
49
+
50
+ readDeadline time.Time
51
+ writeDeadline time.Time
52
+}
53
+
54
+// newStream is used to construct a new stream within
55
+// a given session for an ID
56
+func newStream(session *Session, id uint32, state streamState) *Stream {
57
+ s := &Stream{
58
+ id: id,
59
+ session: session,
60
+ state: state,
61
+ controlHdr: header(make([]byte, headerSize)),
62
+ controlErr: make(chan error, 1),
63
+ sendHdr: header(make([]byte, headerSize)),
64
+ sendErr: make(chan error, 1),
65
+ recvWindow: initialStreamWindow,
66
+ sendWindow: initialStreamWindow,
67
+ recvNotifyCh: make(chan struct{}, 1),
68
+ sendNotifyCh: make(chan struct{}, 1),
69
+ }
70
+ return s
71
+}
72
+
73
+// Session returns the associated stream session
74
+func (s *Stream) Session() *Session {
75
+ return s.session
76
+}
77
+
78
+// StreamID returns the ID of this stream
79
+func (s *Stream) StreamID() uint32 {
80
+ return s.id
81
+}
82
+
83
+// Read is used to read from the stream
84
+func (s *Stream) Read(b []byte) (n int, err error) {
85
+ defer asyncNotify(s.recvNotifyCh)
86
+START:
87
+ s.stateLock.Lock()
88
+ switch s.state {
89
+ case streamRemoteClose:
90
+ fallthrough
91
+ case streamClosed:
92
+ if s.recvBuf.Len() == 0 {
93
+ s.stateLock.Unlock()
94
+ return 0, io.EOF
95
+ }
96
+ case streamReset:
97
+ s.stateLock.Unlock()
98
+ return 0, ErrConnectionReset
99
+ }
100
+ s.stateLock.Unlock()
101
+
102
+ // If there is no data available, block
103
+ s.recvLock.Lock()
104
+ if s.recvBuf.Len() == 0 {
105
+ s.recvLock.Unlock()
106
+ goto WAIT
107
+ }
108
+
109
+ // Read any bytes
110
+ n, _ = s.recvBuf.Read(b)
111
+ s.recvLock.Unlock()
112
+
113
+ // Send a window update potentially
114
+ err = s.sendWindowUpdate()
115
+ return n, err
116
+
117
+WAIT:
118
+ var timeout <-chan time.Time
119
+ if !s.readDeadline.IsZero() {
120
+ delay := s.readDeadline.Sub(time.Now())
121
+ timeout = time.After(delay)
122
+ }
123
+ select {
124
+ case <-s.recvNotifyCh:
125
+ goto START
126
+ case <-timeout:
127
+ return 0, ErrTimeout
128
+ }
129
+}
130
+
131
+// Write is used to write to the stream
132
+func (s *Stream) Write(b []byte) (n int, err error) {
133
+ s.sendLock.Lock()
134
+ defer s.sendLock.Unlock()
135
+ total := 0
136
+ for total < len(b) {
137
+ n, err := s.write(b[total:])
138
+ total += n
139
+ if err != nil {
140
+ return total, err
141
+ }
142
+ }
143
+ return total, nil
144
+}
145
+
146
+// write is used to write to the stream, may return on
147
+// a short write.
148
+func (s *Stream) write(b []byte) (n int, err error) {
149
+ var flags uint16
150
+ var max uint32
151
+ var body io.Reader
152
+START:
153
+ s.stateLock.Lock()
154
+ switch s.state {
155
+ case streamLocalClose:
156
+ fallthrough
157
+ case streamClosed:
158
+ s.stateLock.Unlock()
159
+ return 0, ErrStreamClosed
160
+ case streamReset:
161
+ s.stateLock.Unlock()
162
+ return 0, ErrConnectionReset
163
+ }
164
+ s.stateLock.Unlock()
165
+
166
+ // If there is no data available, block
167
+ window := atomic.LoadUint32(&s.sendWindow)
168
+ if window == 0 {
169
+ goto WAIT
170
+ }
171
+
172
+ // Determine the flags if any
173
+ flags = s.sendFlags()
174
+
175
+ // Send up to our send window
176
+ max = min(window, uint32(len(b)))
177
+ body = bytes.NewReader(b[:max])
178
+
179
+ // Send the header
180
+ s.sendHdr.encode(typeData, flags, s.id, max)
181
+ if err := s.session.waitForSendErr(s.sendHdr, body, s.sendErr); err != nil {
182
+ return 0, err
183
+ }
184
+
185
+ // Reduce our send window
186
+ atomic.AddUint32(&s.sendWindow, ^uint32(max-1))
187
+
188
+ // Unlock
189
+ return int(max), err
190
+
191
+WAIT:
192
+ var timeout <-chan time.Time
193
+ if !s.writeDeadline.IsZero() {
194
+ delay := s.writeDeadline.Sub(time.Now())
195
+ timeout = time.After(delay)
196
+ }
197
+ select {
198
+ case <-s.sendNotifyCh:
199
+ goto START
200
+ case <-timeout:
201
+ return 0, ErrTimeout
202
+ }
203
+ return 0, nil
204
+}
205
+
206
+// sendFlags determines any flags that are appropriate
207
+// based on the current stream state
208
+func (s *Stream) sendFlags() uint16 {
209
+ s.stateLock.Lock()
210
+ defer s.stateLock.Unlock()
211
+ var flags uint16
212
+ switch s.state {
213
+ case streamInit:
214
+ flags |= flagSYN
215
+ s.state = streamSYNSent
216
+ case streamSYNReceived:
217
+ flags |= flagACK
218
+ s.state = streamEstablished
219
+ }
220
+ return flags
221
+}
222
+
223
+// sendWindowUpdate potentially sends a window update enabling
224
+// further writes to take place. Must be invoked with the lock.
225
+func (s *Stream) sendWindowUpdate() error {
226
+ s.controlHdrLock.Lock()
227
+ defer s.controlHdrLock.Unlock()
228
+
229
+ // Determine the delta update
230
+ max := s.session.config.MaxStreamWindowSize
231
+ delta := max - atomic.LoadUint32(&s.recvWindow)
232
+
233
+ // Determine the flags if any
234
+ flags := s.sendFlags()
235
+
236
+ // Check if we can omit the update
237
+ if delta < (max/2) && flags == 0 {
238
+ return nil
239
+ }
240
+
241
+ // Update our window
242
+ atomic.AddUint32(&s.recvWindow, delta)
243
+
244
+ // Send the header
245
+ s.controlHdr.encode(typeWindowUpdate, flags, s.id, delta)
246
+ if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil {
247
+ return err
248
+ }
249
+ return nil
250
+}
251
+
252
+// sendClose is used to send a FIN
253
+func (s *Stream) sendClose() error {
254
+ s.controlHdrLock.Lock()
255
+ defer s.controlHdrLock.Unlock()
256
+
257
+ flags := s.sendFlags()
258
+ flags |= flagFIN
259
+ s.controlHdr.encode(typeWindowUpdate, flags, s.id, 0)
260
+ if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil {
261
+ return err
262
+ }
263
+ return nil
264
+}
265
+
266
+// Close is used to close the stream
267
+func (s *Stream) Close() error {
268
+ s.stateLock.Lock()
269
+ switch s.state {
270
+ // Opened means we need to signal a close
271
+ case streamSYNSent:
272
+ fallthrough
273
+ case streamSYNReceived:
274
+ fallthrough
275
+ case streamEstablished:
276
+ s.state = streamLocalClose
277
+ goto SEND_CLOSE
278
+
279
+ case streamLocalClose:
280
+ case streamRemoteClose:
281
+ s.state = streamClosed
282
+ s.session.closeStream(s.id)
283
+ goto SEND_CLOSE
284
+
285
+ case streamClosed:
286
+ case streamReset:
287
+ default:
288
+ panic("unhandled state")
289
+ }
290
+ s.stateLock.Unlock()
291
+ return nil
292
+SEND_CLOSE:
293
+ s.stateLock.Unlock()
294
+ s.sendClose()
295
+ s.notifyWaiting()
296
+ return nil
297
+}
298
+
299
+// forceClose is used for when the session is exiting
300
+func (s *Stream) forceClose() {
301
+ s.stateLock.Lock()
302
+ s.state = streamClosed
303
+ s.stateLock.Unlock()
304
+ s.notifyWaiting()
305
+}
306
+
307
+// processFlags is used to update the state of the stream
308
+// based on set flags, if any. Lock must be held
309
+func (s *Stream) processFlags(flags uint16) error {
310
+ s.stateLock.Lock()
311
+ defer s.stateLock.Unlock()
312
+ if flags&flagACK == flagACK {
313
+ if s.state == streamSYNSent {
314
+ s.state = streamEstablished
315
+ }
316
+
317
+ } else if flags&flagFIN == flagFIN {
318
+ switch s.state {
319
+ case streamSYNSent:
320
+ fallthrough
321
+ case streamSYNReceived:
322
+ fallthrough
323
+ case streamEstablished:
324
+ s.state = streamRemoteClose
325
+ s.notifyWaiting()
326
+ case streamLocalClose:
327
+ s.state = streamClosed
328
+ s.session.closeStream(s.id)
329
+ s.notifyWaiting()
330
+ default:
331
+ s.session.logger.Printf("[ERR] yamux: unexpected FIN flag in state %d", s.state)
332
+ return ErrUnexpectedFlag
333
+ }
334
+ } else if flags&flagRST == flagRST {
335
+ s.state = streamReset
336
+ s.session.closeStream(s.id)
337
+ s.notifyWaiting()
338
+ }
339
+ return nil
340
+}
341
+
342
+// notifyWaiting notifies all the waiting channels
343
+func (s *Stream) notifyWaiting() {
344
+ asyncNotify(s.recvNotifyCh)
345
+ asyncNotify(s.sendNotifyCh)
346
+}
347
+
348
+// incrSendWindow updates the size of our send window
349
+func (s *Stream) incrSendWindow(hdr header, flags uint16) error {
350
+ if err := s.processFlags(flags); err != nil {
351
+ return err
352
+ }
353
+
354
+ // Increase window, unblock a sender
355
+ atomic.AddUint32(&s.sendWindow, hdr.Length())
356
+ asyncNotify(s.sendNotifyCh)
357
+ return nil
358
+}
359
+
360
+// readData is used to handle a data frame
361
+func (s *Stream) readData(hdr header, flags uint16, conn io.Reader) error {
362
+ if err := s.processFlags(flags); err != nil {
363
+ return err
364
+ }
365
+
366
+ // Check that our recv window is not exceeded
367
+ length := hdr.Length()
368
+ if length == 0 {
369
+ return nil
370
+ }
371
+ if remain := atomic.LoadUint32(&s.recvWindow); length > remain {
372
+ s.session.logger.Printf("[ERR] yamux: receive window exceeded (stream: %d, remain: %d, recv: %d)", s.id, remain, length)
373
+ return ErrRecvWindowExceeded
374
+ }
375
+
376
+ // Wrap in a limited reader
377
+ conn = &io.LimitedReader{R: conn, N: int64(length)}
378
+
379
+ // Copy into buffer
380
+ s.recvLock.Lock()
381
+ if _, err := io.Copy(&s.recvBuf, conn); err != nil {
382
+ s.session.logger.Printf("[ERR] yamux: Failed to read stream data: %v", err)
383
+ s.recvLock.Unlock()
384
+ return err
385
+ }
386
+
387
+ // Decrement the receive window
388
+ atomic.AddUint32(&s.recvWindow, ^uint32(length-1))
389
+ s.recvLock.Unlock()
390
+
391
+ // Unblock any readers
392
+ asyncNotify(s.recvNotifyCh)
393
+ return nil
394
+}
395
+
396
+// SetDeadline sets the read and write deadlines
397
+func (s *Stream) SetDeadline(t time.Time) error {
398
+ if err := s.SetReadDeadline(t); err != nil {
399
+ return err
400
+ }
401
+ if err := s.SetWriteDeadline(t); err != nil {
402
+ return err
403
+ }
404
+ return nil
405
+}
406
+
407
+// SetReadDeadline sets the deadline for future Read calls.
408
+func (s *Stream) SetReadDeadline(t time.Time) error {
409
+ s.readDeadline = t
410
+ return nil
411
+}
412
+
413
+// SetWriteDeadline sets the deadline for future Write calls
414
+func (s *Stream) SetWriteDeadline(t time.Time) error {
415
+ s.writeDeadline = t
416
+ return nil
417
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/util.go
new
+28
@@ -0,0 +1,28 @@
1
+package yamux
2
+
3
+// asyncSendErr is used to try an async send of an error
4
+func asyncSendErr(ch chan error, err error) {
5
+ if ch == nil {
6
+ return
7
+ }
8
+ select {
9
+ case ch <- err:
10
+ default:
11
+ }
12
+}
13
+
14
+// asyncNotify is used to signal a waiting goroutine
15
+func asyncNotify(ch chan struct{}) {
16
+ select {
17
+ case ch <- struct{}{}:
18
+ default:
19
+ }
20
+}
21
+
22
+// min computes the minimum of two values
23
+func min(a, b uint32) uint32 {
24
+ if a < b {
25
+ return a
26
+ }
27
+ return b
28
+}
Godeps/_workspace/src/github.com/hashicorp/yamux/util_test.go
new
+50
@@ -0,0 +1,50 @@
1
+package yamux
2
+
3
+import (
4
+ "testing"
5
+)
6
+
7
+func TestAsyncSendErr(t *testing.T) {
8
+ ch := make(chan error)
9
+ asyncSendErr(ch, ErrTimeout)
10
+ select {
11
+ case <-ch:
12
+ t.Fatalf("should not get")
13
+ default:
14
+ }
15
+
16
+ ch = make(chan error, 1)
17
+ asyncSendErr(ch, ErrTimeout)
18
+ select {
19
+ case <-ch:
20
+ default:
21
+ t.Fatalf("should get")
22
+ }
23
+}
24
+
25
+func TestAsyncNotify(t *testing.T) {
26
+ ch := make(chan struct{})
27
+ asyncNotify(ch)
28
+ select {
29
+ case <-ch:
30
+ t.Fatalf("should not get")
31
+ default:
32
+ }
33
+
34
+ ch = make(chan struct{}, 1)
35
+ asyncNotify(ch)
36
+ select {
37
+ case <-ch:
38
+ default:
39
+ t.Fatalf("should get")
40
+ }
41
+}
42
+
43
+func TestMin(t *testing.T) {
44
+ if min(1, 2) != 1 {
45
+ t.Fatalf("bad")
46
+ }
47
+ if min(2, 1) != 1 {
48
+ t.Fatalf("bad")
49
+ }
50
+}
Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/spdystream/spdystream.go
+1
-1
@@ -5,7 +5,7 @@ import (
5
"net/http"
6
7
pst "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport"
8
- ss "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/spdystream"
8
+ ss "github.com/jbenet/spdystream"
9
)
10
11
// stream implements pst.Stream using a ss.Stream
Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/yamux/yamux.go
new
+90
@@ -0,0 +1,90 @@
1
+package peerstream_yamux
2
+
3
+import (
4
+ "io/ioutil"
5
+ "net"
6
+ "time"
7
+
8
+ yamux "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/hashicorp/yamux"
9
+ pst "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport"
10
+)
11
+
12
+// stream implements pst.Stream using a ss.Stream
13
+type stream yamux.Stream
14
+
15
+func (s *stream) yamuxStream() *yamux.Stream {
16
+ return (*yamux.Stream)(s)
17
+}
18
+
19
+func (s *stream) Read(buf []byte) (int, error) {
20
+ return s.yamuxStream().Read(buf)
21
+}
22
+
23
+func (s *stream) Write(buf []byte) (int, error) {
24
+ return s.yamuxStream().Write(buf)
25
+}
26
+
27
+func (s *stream) Close() error {
28
+ return s.yamuxStream().Close()
29
+}
30
+
31
+// Conn is a connection to a remote peer.
32
+type conn yamux.Session
33
+
34
+func (c *conn) yamuxSession() *yamux.Session {
35
+ return (*yamux.Session)(c)
36
+}
37
+
38
+func (c *conn) Close() error {
39
+ return c.yamuxSession().Close()
40
+}
41
+
42
+// OpenStream creates a new stream.
43
+func (c *conn) OpenStream() (pst.Stream, error) {
44
+ s, err := c.yamuxSession().OpenStream()
45
+ if err != nil {
46
+ return nil, err
47
+ }
48
+
49
+ return (*stream)(s), nil
50
+}
51
+
52
+// Serve starts listening for incoming requests and handles them
53
+// using given StreamHandler
54
+func (c *conn) Serve(handler pst.StreamHandler) {
55
+ for { // accept loop
56
+ s, err := c.yamuxSession().AcceptStream()
57
+ if err != nil {
58
+ return // err always means closed.
59
+ }
60
+ go handler((*stream)(s))
61
+ }
62
+}
63
+
64
+// Transport is a go-peerstream transport that constructs
65
+// yamux-backed connections.
66
+type Transport yamux.Config
67
+
68
+// DefaultTransport has default settings for yamux
69
+var DefaultTransport = (*Transport)(&yamux.Config{
70
+ AcceptBacklog: 256, // from yamux.DefaultConfig
71
+ EnableKeepAlive: true, // from yamux.DefaultConfig
72
+ KeepAliveInterval: 30 * time.Second, // from yamux.DefaultConfig
73
+ MaxStreamWindowSize: uint32(256 * 1024), // from yamux.DefaultConfig
74
+ LogOutput: ioutil.Discard,
75
+})
76
+
77
+func (t *Transport) NewConn(nc net.Conn, isServer bool) (pst.Conn, error) {
78
+ var s *yamux.Session
79
+ var err error
80
+ if isServer {
81
+ s, err = yamux.Server(nc, t.Config())
82
+ } else {
83
+ s, err = yamux.Client(nc, t.Config())
84
+ }
85
+ return (*conn)(s), err
86
+}
87
+
88
+func (t *Transport) Config() *yamux.Config {
89
+ return (*yamux.Config)(t)
90
+}
Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/yamux/yamux_test.go
new
+11
@@ -0,0 +1,11 @@
1
+package peerstream_yamux
2
+
3
+import (
4
+ "testing"
5
+
6
+ psttest "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/test"
7
+)
8
+
9
+func TestYamuxTransport(t *testing.T) {
10
+ psttest.SubtestAll(t, DefaultTransport)
11
+}
Godeps/_workspace/src/github.com/jbenet/spdystream/CONTRIBUTING.md
deleted
-13
@@ -1,13 +0,0 @@
1
-# Contributing to SpdyStream
2
-
3
-Want to hack on spdystream? Awesome! Here are instructions to get you
4
-started.
5
-
6
-SpdyStream is a part of the [Docker](https://docker.io) project, and follows
7
-the same rules and principles. If you're already familiar with the way
8
-Docker does things, you'll feel right at home.
9
-
10
-Otherwise, go read
11
-[Docker's contributions guidelines](https://github.com/dotcloud/docker/blob/master/CONTRIBUTING.md).
12
-
13
-Happy hacking!
Godeps/_workspace/src/github.com/jbenet/spdystream/LICENSE
deleted
-191
@@ -1,191 +0,0 @@
1
-
2
- Apache License
3
- Version 2.0, January 2004
4
- http://www.apache.org/licenses/
5
-
6
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
-
8
- 1. Definitions.
9
-
10
- "License" shall mean the terms and conditions for use, reproduction,
11
- and distribution as defined by Sections 1 through 9 of this document.
12
-
13
- "Licensor" shall mean the copyright owner or entity authorized by
14
- the copyright owner that is granting the License.
15
-
16
- "Legal Entity" shall mean the union of the acting entity and all
17
- other entities that control, are controlled by, or are under common
18
- control with that entity. For the purposes of this definition,
19
- "control" means (i) the power, direct or indirect, to cause the
20
- direction or management of such entity, whether by contract or
21
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
- outstanding shares, or (iii) beneficial ownership of such entity.
23
-
24
- "You" (or "Your") shall mean an individual or Legal Entity
25
- exercising permissions granted by this License.
26
-
27
- "Source" form shall mean the preferred form for making modifications,
28
- including but not limited to software source code, documentation
29
- source, and configuration files.
30
-
31
- "Object" form shall mean any form resulting from mechanical
32
- transformation or translation of a Source form, including but
33
- not limited to compiled object code, generated documentation,
34
- and conversions to other media types.
35
-
36
- "Work" shall mean the work of authorship, whether in Source or
37
- Object form, made available under the License, as indicated by a
38
- copyright notice that is included in or attached to the work
39
- (an example is provided in the Appendix below).
40
-
41
- "Derivative Works" shall mean any work, whether in Source or Object
42
- form, that is based on (or derived from) the Work and for which the
43
- editorial revisions, annotations, elaborations, or other modifications
44
- represent, as a whole, an original work of authorship. For the purposes
45
- of this License, Derivative Works shall not include works that remain
46
- separable from, or merely link (or bind by name) to the interfaces of,
47
- the Work and Derivative Works thereof.
48
-
49
- "Contribution" shall mean any work of authorship, including
50
- the original version of the Work and any modifications or additions
51
- to that Work or Derivative Works thereof, that is intentionally
52
- submitted to Licensor for inclusion in the Work by the copyright owner
53
- or by an individual or Legal Entity authorized to submit on behalf of
54
- the copyright owner. For the purposes of this definition, "submitted"
55
- means any form of electronic, verbal, or written communication sent
56
- to the Licensor or its representatives, including but not limited to
57
- communication on electronic mailing lists, source code control systems,
58
- and issue tracking systems that are managed by, or on behalf of, the
59
- Licensor for the purpose of discussing and improving the Work, but
60
- excluding communication that is conspicuously marked or otherwise
61
- designated in writing by the copyright owner as "Not a Contribution."
62
-
63
- "Contributor" shall mean Licensor and any individual or Legal Entity
64
- on behalf of whom a Contribution has been received by Licensor and
65
- subsequently incorporated within the Work.
66
-
67
- 2. Grant of Copyright License. Subject to the terms and conditions of
68
- this License, each Contributor hereby grants to You a perpetual,
69
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
- copyright license to reproduce, prepare Derivative Works of,
71
- publicly display, publicly perform, sublicense, and distribute the
72
- Work and such Derivative Works in Source or Object form.
73
-
74
- 3. Grant of Patent License. Subject to the terms and conditions of
75
- this License, each Contributor hereby grants to You a perpetual,
76
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
- (except as stated in this section) patent license to make, have made,
78
- use, offer to sell, sell, import, and otherwise transfer the Work,
79
- where such license applies only to those patent claims licensable
80
- by such Contributor that are necessarily infringed by their
81
- Contribution(s) alone or by combination of their Contribution(s)
82
- with the Work to which such Contribution(s) was submitted. If You
83
- institute patent litigation against any entity (including a
84
- cross-claim or counterclaim in a lawsuit) alleging that the Work
85
- or a Contribution incorporated within the Work constitutes direct
86
- or contributory patent infringement, then any patent licenses
87
- granted to You under this License for that Work shall terminate
88
- as of the date such litigation is filed.
89
-
90
- 4. Redistribution. You may reproduce and distribute copies of the
91
- Work or Derivative Works thereof in any medium, with or without
92
- modifications, and in Source or Object form, provided that You
93
- meet the following conditions:
94
-
95
- (a) You must give any other recipients of the Work or
96
- Derivative Works a copy of this License; and
97
-
98
- (b) You must cause any modified files to carry prominent notices
99
- stating that You changed the files; and
100
-
101
- (c) You must retain, in the Source form of any Derivative Works
102
- that You distribute, all copyright, patent, trademark, and
103
- attribution notices from the Source form of the Work,
104
- excluding those notices that do not pertain to any part of
105
- the Derivative Works; and
106
-
107
- (d) If the Work includes a "NOTICE" text file as part of its
108
- distribution, then any Derivative Works that You distribute must
109
- include a readable copy of the attribution notices contained
110
- within such NOTICE file, excluding those notices that do not
111
- pertain to any part of the Derivative Works, in at least one
112
- of the following places: within a NOTICE text file distributed
113
- as part of the Derivative Works; within the Source form or
114
- documentation, if provided along with the Derivative Works; or,
115
- within a display generated by the Derivative Works, if and
116
- wherever such third-party notices normally appear. The contents
117
- of the NOTICE file are for informational purposes only and
118
- do not modify the License. You may add Your own attribution
119
- notices within Derivative Works that You distribute, alongside
120
- or as an addendum to the NOTICE text from the Work, provided
121
- that such additional attribution notices cannot be construed
122
- as modifying the License.
123
-
124
- You may add Your own copyright statement to Your modifications and
125
- may provide additional or different license terms and conditions
126
- for use, reproduction, or distribution of Your modifications, or
127
- for any such Derivative Works as a whole, provided Your use,
128
- reproduction, and distribution of the Work otherwise complies with
129
- the conditions stated in this License.
130
-
131
- 5. Submission of Contributions. Unless You explicitly state otherwise,
132
- any Contribution intentionally submitted for inclusion in the Work
133
- by You to the Licensor shall be under the terms and conditions of
134
- this License, without any additional terms or conditions.
135
- Notwithstanding the above, nothing herein shall supersede or modify
136
- the terms of any separate license agreement you may have executed
137
- with Licensor regarding such Contributions.
138
-
139
- 6. Trademarks. This License does not grant permission to use the trade
140
- names, trademarks, service marks, or product names of the Licensor,
141
- except as required for reasonable and customary use in describing the
142
- origin of the Work and reproducing the content of the NOTICE file.
143
-
144
- 7. Disclaimer of Warranty. Unless required by applicable law or
145
- agreed to in writing, Licensor provides the Work (and each
146
- Contributor provides its Contributions) on an "AS IS" BASIS,
147
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
- implied, including, without limitation, any warranties or conditions
149
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
- PARTICULAR PURPOSE. You are solely responsible for determining the
151
- appropriateness of using or redistributing the Work and assume any
152
- risks associated with Your exercise of permissions under this License.
153
-
154
- 8. Limitation of Liability. In no event and under no legal theory,
155
- whether in tort (including negligence), contract, or otherwise,
156
- unless required by applicable law (such as deliberate and grossly
157
- negligent acts) or agreed to in writing, shall any Contributor be
158
- liable to You for damages, including any direct, indirect, special,
159
- incidental, or consequential damages of any character arising as a
160
- result of this License or out of the use or inability to use the
161
- Work (including but not limited to damages for loss of goodwill,
162
- work stoppage, computer failure or malfunction, or any and all
163
- other commercial damages or losses), even if such Contributor
164
- has been advised of the possibility of such damages.
165
-
166
- 9. Accepting Warranty or Additional Liability. While redistributing
167
- the Work or Derivative Works thereof, You may choose to offer,
168
- and charge a fee for, acceptance of support, warranty, indemnity,
169
- or other liability obligations and/or rights consistent with this
170
- License. However, in accepting such obligations, You may act only
171
- on Your own behalf and on Your sole responsibility, not on behalf
172
- of any other Contributor, and only if You agree to indemnify,
173
- defend, and hold each Contributor harmless for any liability
174
- incurred by, or claims asserted against, such Contributor by reason
175
- of your accepting any such warranty or additional liability.
176
-
177
- END OF TERMS AND CONDITIONS
178
-
179
- Copyright 2014 Docker, Inc.
180
-
181
- Licensed under the Apache License, Version 2.0 (the "License");
182
- you may not use this file except in compliance with the License.
183
- You may obtain a copy of the License at
184
-
185
- http://www.apache.org/licenses/LICENSE-2.0
186
-
187
- Unless required by applicable law or agreed to in writing, software
188
- distributed under the License is distributed on an "AS IS" BASIS,
189
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190
- See the License for the specific language governing permissions and
191
- limitations under the License.
Godeps/_workspace/src/github.com/jbenet/spdystream/MAINTAINERS
deleted
-1
@@ -1 +0,0 @@
1
-Derek McGowan <derek@docker.com> (@dmcg)
Godeps/_workspace/src/github.com/jbenet/spdystream/README.md
deleted
-78
@@ -1,78 +0,0 @@
1
-# SpdyStream
2
-
3
-A multiplexed stream library using spdy
4
-
5
-## Usage
6
-
7
-Client example (connecting to mirroring server without auth)
8
-
9
-```go
10
-package main
11
-
12
-import (
13
- "fmt"
14
- "github.com/docker/spdystream"
15
- "net"
16
- "net/http"
17
-)
18
-
19
-func main() {
20
- conn, err := net.Dial("tcp", "localhost:8080")
21
- if err != nil {
22
- panic(err)
23
- }
24
- spdyConn, err := spdystream.NewConnection(conn, false)
25
- if err != nil {
26
- panic(err)
27
- }
28
- go spdyConn.Serve(spdystream.NoOpStreamHandler)
29
- stream, err := spdyConn.CreateStream(http.Header{}, nil, false)
30
- if err != nil {
31
- panic(err)
32
- }
33
-
34
- stream.Wait()
35
-
36
- fmt.Fprint(stream, "Writing to stream")
37
-
38
- buf := make([]byte, 25)
39
- stream.Read(buf)
40
- fmt.Println(string(buf))
41
-
42
- stream.Close()
43
-}
44
-```
45
-
46
-Server example (mirroring server without auth)
47
-
48
-```go
49
-package main
50
-
51
-import (
52
- "github.com/docker/spdystream"
53
- "net"
54
-)
55
-
56
-func main() {
57
- listener, err := net.Listen("tcp", "localhost:8080")
58
- if err != nil {
59
- panic(err)
60
- }
61
- for {
62
- conn, err := listener.Accept()
63
- if err != nil {
64
- panic(err)
65
- }
66
- spdyConn, err := spdystream.NewConnection(conn, true)
67
- if err != nil {
68
- panic(err)
69
- }
70
- go spdyConn.Serve(spdystream.MirrorStreamHandler)
71
- }
72
-}
73
-```
74
-
75
-## Copyright and license
76
-
77
-Code and documentation copyright 2013-2014 Docker, inc. Code released under the Apache 2.0 license.
78
-Docs released under Creative commons.
Godeps/_workspace/src/github.com/jbenet/spdystream/connection.go
deleted
-804
@@ -1,804 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "errors"
5
- "fmt"
6
- "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/spdy"
7
- "io"
8
- "net"
9
- "net/http"
10
- "sync"
11
- "time"
12
-)
13
-
14
-var (
15
- ErrInvalidStreamId = errors.New("Invalid stream id")
16
- ErrTimeout = errors.New("Timeout occured")
17
- ErrReset = errors.New("Stream reset")
18
- ErrWriteClosedStream = errors.New("Write on closed stream")
19
-)
20
-
21
-const (
22
- FRAME_WORKERS = 5
23
- QUEUE_SIZE = 50
24
-)
25
-
26
-type StreamHandler func(stream *Stream)
27
-
28
-type AuthHandler func(header http.Header, slot uint8, parent uint32) bool
29
-
30
-type Connection struct {
31
- conn net.Conn
32
- framer *spdy.Framer
33
- writeLock sync.Mutex
34
-
35
- closeChan chan bool
36
- goneAway bool
37
- lastStreamChan chan<- *Stream
38
- goAwayTimeout time.Duration
39
- closeTimeout time.Duration
40
-
41
- streamLock *sync.RWMutex
42
- streamCond *sync.Cond
43
- streams map[spdy.StreamId]*Stream
44
-
45
- nextIdLock sync.Mutex
46
- receiveIdLock sync.Mutex
47
- nextStreamId spdy.StreamId
48
- receivedStreamId spdy.StreamId
49
-
50
- pingIdLock sync.Mutex
51
- pingId uint32
52
- pingChans map[uint32]chan error
53
-
54
- shutdownLock sync.Mutex
55
- shutdownChan chan error
56
- hasShutdown bool
57
-}
58
-
59
-// NewConnection creates a new spdy connection from an existing
60
-// network connection.
61
-func NewConnection(conn net.Conn, server bool) (*Connection, error) {
62
- framer, framerErr := spdy.NewFramer(conn, conn)
63
- if framerErr != nil {
64
- return nil, framerErr
65
- }
66
- var sid spdy.StreamId
67
- var rid spdy.StreamId
68
- var pid uint32
69
- if server {
70
- sid = 2
71
- rid = 1
72
- pid = 2
73
- } else {
74
- sid = 1
75
- rid = 2
76
- pid = 1
77
- }
78
-
79
- streamLock := new(sync.RWMutex)
80
- streamCond := sync.NewCond(streamLock)
81
-
82
- session := &Connection{
83
- conn: conn,
84
- framer: framer,
85
-
86
- closeChan: make(chan bool),
87
- goAwayTimeout: time.Duration(0),
88
- closeTimeout: time.Duration(0),
89
-
90
- streamLock: streamLock,
91
- streamCond: streamCond,
92
- streams: make(map[spdy.StreamId]*Stream),
93
- nextStreamId: sid,
94
- receivedStreamId: rid,
95
-
96
- pingId: pid,
97
- pingChans: make(map[uint32]chan error),
98
-
99
- shutdownChan: make(chan error),
100
- }
101
-
102
- return session, nil
103
-}
104
-
105
-// Ping sends a ping frame across the connection and
106
-// returns the response time
107
-func (s *Connection) Ping() (time.Duration, error) {
108
- pid := s.pingId
109
- s.pingIdLock.Lock()
110
- if s.pingId > 0x7ffffffe {
111
- s.pingId = s.pingId - 0x7ffffffe
112
- } else {
113
- s.pingId = s.pingId + 2
114
- }
115
- s.pingIdLock.Unlock()
116
- pingChan := make(chan error)
117
- s.pingChans[pid] = pingChan
118
- defer delete(s.pingChans, pid)
119
-
120
- frame := &spdy.PingFrame{Id: pid}
121
- startTime := time.Now()
122
- s.writeLock.Lock()
123
- writeErr := s.framer.WriteFrame(frame)
124
- s.writeLock.Unlock()
125
- if writeErr != nil {
126
- return time.Duration(0), writeErr
127
- }
128
- select {
129
- case <-s.closeChan:
130
- return time.Duration(0), errors.New("connection closed")
131
- case err, ok := <-pingChan:
132
- if ok && err != nil {
133
- return time.Duration(0), err
134
- }
135
- break
136
- }
137
- return time.Now().Sub(startTime), nil
138
-}
139
-
140
-// Serve handles frames sent from the server, including reply frames
141
-// which are needed to fully initiate connections. Both clients and servers
142
-// should call Serve in a separate goroutine before creating streams.
143
-func (s *Connection) Serve(newHandler StreamHandler) {
144
- // Parition queues to ensure stream frames are handled
145
- // by the same worker, ensuring order is maintained
146
- frameQueues := make([]*PriorityFrameQueue, FRAME_WORKERS)
147
- for i := 0; i < FRAME_WORKERS; i++ {
148
- frameQueues[i] = NewPriorityFrameQueue(QUEUE_SIZE)
149
- // Ensure frame queue is drained when connection is closed
150
- go func(frameQueue *PriorityFrameQueue) {
151
- <-s.closeChan
152
- frameQueue.Drain()
153
- }(frameQueues[i])
154
-
155
- go s.frameHandler(frameQueues[i], newHandler)
156
- }
157
-
158
- var partitionRoundRobin int
159
- for {
160
- readFrame, err := s.framer.ReadFrame()
161
- if err != nil {
162
- if err != io.EOF {
163
- fmt.Errorf("frame read error: %s", err)
164
- } else {
165
- debugMessage("EOF received")
166
- }
167
- break
168
- }
169
- var priority uint8
170
- var partition int
171
- switch frame := readFrame.(type) {
172
- case *spdy.SynStreamFrame:
173
- if s.checkStreamFrame(frame) {
174
- priority = frame.Priority
175
- partition = int(frame.StreamId % FRAME_WORKERS)
176
- debugMessage("(%p) Add stream frame: %d ", s, frame.StreamId)
177
- s.addStreamFrame(frame)
178
- } else {
179
- debugMessage("(%p) Rejected stream frame: %d ", s, frame.StreamId)
180
- continue
181
- }
182
- case *spdy.SynReplyFrame:
183
- priority = s.getStreamPriority(frame.StreamId)
184
- partition = int(frame.StreamId % FRAME_WORKERS)
185
- case *spdy.DataFrame:
186
- priority = s.getStreamPriority(frame.StreamId)
187
- partition = int(frame.StreamId % FRAME_WORKERS)
188
- case *spdy.RstStreamFrame:
189
- priority = s.getStreamPriority(frame.StreamId)
190
- partition = int(frame.StreamId % FRAME_WORKERS)
191
- case *spdy.HeadersFrame:
192
- priority = s.getStreamPriority(frame.StreamId)
193
- partition = int(frame.StreamId % FRAME_WORKERS)
194
- case *spdy.PingFrame:
195
- priority = 0
196
- partition = partitionRoundRobin
197
- partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS
198
- case *spdy.GoAwayFrame:
199
- priority = 0
200
- partition = partitionRoundRobin
201
- partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS
202
- default:
203
- priority = 7
204
- partition = partitionRoundRobin
205
- partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS
206
- }
207
- frameQueues[partition].Push(readFrame, priority)
208
- }
209
- close(s.closeChan)
210
-
211
- s.streamCond.L.Lock()
212
- s.streams = make(map[spdy.StreamId]*Stream)
213
- s.streamCond.Broadcast()
214
- s.streamCond.L.Unlock()
215
-}
216
-
217
-func (s *Connection) frameHandler(frameQueue *PriorityFrameQueue, newHandler StreamHandler) {
218
- for {
219
- popFrame := frameQueue.Pop()
220
- if popFrame == nil {
221
- return
222
- }
223
-
224
- var frameErr error
225
- switch frame := popFrame.(type) {
226
- case *spdy.SynStreamFrame:
227
- frameErr = s.handleStreamFrame(frame, newHandler)
228
- case *spdy.SynReplyFrame:
229
- frameErr = s.handleReplyFrame(frame)
230
- case *spdy.DataFrame:
231
- frameErr = s.handleDataFrame(frame)
232
- case *spdy.RstStreamFrame:
233
- frameErr = s.handleResetFrame(frame)
234
- case *spdy.HeadersFrame:
235
- frameErr = s.handleHeaderFrame(frame)
236
- case *spdy.PingFrame:
237
- frameErr = s.handlePingFrame(frame)
238
- case *spdy.GoAwayFrame:
239
- frameErr = s.handleGoAwayFrame(frame)
240
- default:
241
- frameErr = fmt.Errorf("unhandled frame type: %T", frame)
242
- }
243
-
244
- if frameErr != nil {
245
- fmt.Errorf("frame handling error: %s", frameErr)
246
- }
247
- }
248
-}
249
-
250
-func (s *Connection) getStreamPriority(streamId spdy.StreamId) uint8 {
251
- stream, streamOk := s.getStream(streamId)
252
- if !streamOk {
253
- return 7
254
- }
255
- return stream.priority
256
-}
257
-
258
-func (s *Connection) addStreamFrame(frame *spdy.SynStreamFrame) {
259
- var parent *Stream
260
- if frame.AssociatedToStreamId != spdy.StreamId(0) {
261
- parent, _ = s.getStream(frame.AssociatedToStreamId)
262
- }
263
-
264
- stream := &Stream{
265
- streamId: frame.StreamId,
266
- parent: parent,
267
- conn: s,
268
- startChan: make(chan error),
269
- headers: frame.Headers,
270
- finished: (frame.CFHeader.Flags & spdy.ControlFlagUnidirectional) != 0x00,
271
- replyCond: sync.NewCond(new(sync.Mutex)),
272
- dataChan: make(chan []byte),
273
- headerChan: make(chan http.Header),
274
- closeChan: make(chan bool),
275
- shutdownChan: make(chan struct{}),
276
- }
277
- if frame.CFHeader.Flags&spdy.ControlFlagFin != 0x00 {
278
- close(stream.dataChan)
279
- close(stream.closeChan)
280
- }
281
-
282
- s.addStream(stream)
283
-}
284
-
285
-// checkStreamFrame checks to see if a stream frame is allowed.
286
-// If the stream is invalid, then a reset frame with protocol error
287
-// will be returned.
288
-func (s *Connection) checkStreamFrame(frame *spdy.SynStreamFrame) bool {
289
- s.receiveIdLock.Lock()
290
- defer s.receiveIdLock.Unlock()
291
- if s.goneAway {
292
- return false
293
- }
294
- validationErr := s.validateStreamId(frame.StreamId)
295
- if validationErr != nil {
296
- go func() {
297
- resetErr := s.sendResetFrame(spdy.ProtocolError, frame.StreamId)
298
- if resetErr != nil {
299
- fmt.Errorf("reset error: %s", resetErr)
300
- }
301
- }()
302
- return false
303
- }
304
- return true
305
-}
306
-
307
-func (s *Connection) handleStreamFrame(frame *spdy.SynStreamFrame, newHandler StreamHandler) error {
308
- stream, ok := s.getStream(frame.StreamId)
309
- if !ok {
310
- return fmt.Errorf("Missing stream: %d", frame.StreamId)
311
- }
312
-
313
- newHandler(stream)
314
-
315
- return nil
316
-}
317
-
318
-func (s *Connection) handleReplyFrame(frame *spdy.SynReplyFrame) error {
319
- debugMessage("(%p) Reply frame received for %d", s, frame.StreamId)
320
- stream, streamOk := s.getStream(frame.StreamId)
321
- if !streamOk {
322
- debugMessage("Reply frame gone away for %d", frame.StreamId)
323
- // Stream has already gone away
324
- return nil
325
- }
326
- if stream.replied {
327
- // Stream has already received reply
328
- return nil
329
- }
330
- stream.replied = true
331
-
332
- // TODO Check for error
333
- if (frame.CFHeader.Flags & spdy.ControlFlagFin) != 0x00 {
334
- s.remoteStreamFinish(stream)
335
- }
336
-
337
- close(stream.startChan)
338
-
339
- return nil
340
-}
341
-
342
-func (s *Connection) handleResetFrame(frame *spdy.RstStreamFrame) error {
343
- stream, streamOk := s.getStream(frame.StreamId)
344
- if !streamOk {
345
- // Stream has already been removed
346
- return nil
347
- }
348
- s.removeStream(stream)
349
- stream.dataLock.Lock()
350
- select {
351
- case <-stream.closeChan:
352
- break
353
- default:
354
- close(stream.dataChan)
355
- close(stream.closeChan)
356
- }
357
- stream.dataLock.Unlock()
358
-
359
- if !stream.replied {
360
- stream.replied = true
361
- stream.startChan <- ErrReset
362
- close(stream.startChan)
363
- }
364
-
365
- stream.finishLock.Lock()
366
- stream.finished = true
367
- stream.finishLock.Unlock()
368
-
369
- return nil
370
-}
371
-
372
-func (s *Connection) handleHeaderFrame(frame *spdy.HeadersFrame) error {
373
- stream, streamOk := s.getStream(frame.StreamId)
374
- if !streamOk {
375
- // Stream has already gone away
376
- return nil
377
- }
378
- if !stream.replied {
379
- // No reply received...Protocol error?
380
- return nil
381
- }
382
-
383
- // TODO limit headers while not blocking (use buffered chan or goroutine?)
384
- select {
385
- case <-stream.closeChan:
386
- return nil
387
- case stream.headerChan <- frame.Headers:
388
- }
389
-
390
- if (frame.CFHeader.Flags & spdy.ControlFlagFin) != 0x00 {
391
- s.remoteStreamFinish(stream)
392
- }
393
-
394
- return nil
395
-}
396
-
397
-func (s *Connection) handleDataFrame(frame *spdy.DataFrame) error {
398
- debugMessage("(%p) Data frame received for %d", s, frame.StreamId)
399
- stream, streamOk := s.getStream(frame.StreamId)
400
- if !streamOk {
401
- debugMessage("Data frame gone away for %d", frame.StreamId)
402
- // Stream has already gone away
403
- return nil
404
- }
405
- if !stream.replied {
406
- debugMessage("Data frame not replied %d", frame.StreamId)
407
- // No reply received...Protocol error?
408
- return nil
409
- }
410
-
411
- debugMessage("(%p) (%d) Data frame handling", stream, stream.streamId)
412
- if len(frame.Data) > 0 {
413
- stream.dataLock.RLock()
414
- select {
415
- case <-stream.closeChan:
416
- break
417
- default:
418
- debugMessage("(%p) (%d) Data frame send chan", stream, stream.streamId)
419
- select {
420
- case stream.dataChan <- frame.Data:
421
- debugMessage("(%p) (%d) Data frame sent", stream, stream.streamId)
422
- case <-stream.shutdownChan:
423
- debugMessage("(%p) (%d) Data frame not sent (stream shut down)", stream, stream.streamId)
424
- }
425
- }
426
- stream.dataLock.RUnlock()
427
- }
428
- if (frame.Flags & spdy.DataFlagFin) != 0x00 {
429
- s.remoteStreamFinish(stream)
430
- }
431
- return nil
432
-}
433
-
434
-func (s *Connection) handlePingFrame(frame *spdy.PingFrame) error {
435
- if s.pingId&0x01 != frame.Id&0x01 {
436
- s.writeLock.Lock()
437
- defer s.writeLock.Unlock()
438
- return s.framer.WriteFrame(frame)
439
- }
440
- pingChan, pingOk := s.pingChans[frame.Id]
441
- if pingOk {
442
- close(pingChan)
443
- }
444
- return nil
445
-}
446
-
447
-func (s *Connection) handleGoAwayFrame(frame *spdy.GoAwayFrame) error {
448
- debugMessage("(%p) Go away received", s)
449
- s.receiveIdLock.Lock()
450
- if s.goneAway {
451
- s.receiveIdLock.Unlock()
452
- return nil
453
- }
454
- s.goneAway = true
455
- s.receiveIdLock.Unlock()
456
-
457
- if s.lastStreamChan != nil {
458
- stream, _ := s.getStream(frame.LastGoodStreamId)
459
- go func() {
460
- s.lastStreamChan <- stream
461
- }()
462
- }
463
-
464
- // Do not block frame handler waiting for closure
465
- go s.shutdown(s.goAwayTimeout)
466
-
467
- return nil
468
-}
469
-
470
-func (s *Connection) remoteStreamFinish(stream *Stream) {
471
- // synchronize closing channel
472
- stream.dataLock.Lock()
473
- select {
474
- case <-stream.closeChan:
475
- break
476
- default:
477
- close(stream.dataChan)
478
- close(stream.closeChan)
479
- }
480
- stream.dataLock.Unlock()
481
-
482
- stream.finishLock.Lock()
483
- if stream.finished {
484
- // Stream is fully closed, cleanup
485
- s.removeStream(stream)
486
- }
487
- stream.finishLock.Unlock()
488
-}
489
-
490
-// CreateStream creates a new spdy stream using the parameters for
491
-// creating the stream frame. The stream frame will be sent upon
492
-// calling this function, however this function does not wait for
493
-// the reply frame. If waiting for the reply is desired, use
494
-// the stream Wait or WaitTimeout function on the stream returned
495
-// by this function.
496
-func (s *Connection) CreateStream(headers http.Header, parent *Stream, fin bool) (*Stream, error) {
497
- streamId := s.getNextStreamId()
498
- if streamId == 0 {
499
- return nil, fmt.Errorf("Unable to get new stream id")
500
- }
501
-
502
- stream := &Stream{
503
- streamId: streamId,
504
- parent: parent,
505
- conn: s,
506
- startChan: make(chan error),
507
- headers: headers,
508
- dataChan: make(chan []byte),
509
- headerChan: make(chan http.Header),
510
- closeChan: make(chan bool),
511
- shutdownChan: make(chan struct{}),
512
- }
513
-
514
- debugMessage("(%p) (%p) Create stream", s, stream)
515
-
516
- s.addStream(stream)
517
-
518
- return stream, s.sendStream(stream, fin)
519
-}
520
-
521
-func (s *Connection) shutdown(closeTimeout time.Duration) {
522
- // TODO Ensure this isn't called multiple times
523
- s.shutdownLock.Lock()
524
- if s.hasShutdown {
525
- s.shutdownLock.Unlock()
526
- return
527
- }
528
- s.hasShutdown = true
529
- s.shutdownLock.Unlock()
530
-
531
- var timeout <-chan time.Time
532
- if closeTimeout > time.Duration(0) {
533
- timeout = time.After(closeTimeout)
534
- }
535
- streamsClosed := make(chan bool)
536
-
537
- go func() {
538
- s.streamCond.L.Lock()
539
- for len(s.streams) > 0 {
540
- debugMessage("Streams opened: %d, %#v", len(s.streams), s.streams)
541
- s.streamCond.Wait()
542
- }
543
- s.streamCond.L.Unlock()
544
- close(streamsClosed)
545
- }()
546
-
547
- var err error
548
- select {
549
- case <-streamsClosed:
550
- // No active streams, close should be safe
551
- err = s.conn.Close()
552
- case <-timeout:
553
- // Force ungraceful close
554
- err = s.conn.Close()
555
- // Wait for cleanup to clear active streams
556
- <-streamsClosed
557
- }
558
-
559
- if err != nil {
560
- duration := 10 * time.Minute
561
- time.AfterFunc(duration, func() {
562
- select {
563
- case err, ok := <-s.shutdownChan:
564
- if ok {
565
- fmt.Errorf("Unhandled close error after %s: %s", duration, err)
566
- }
567
- default:
568
- }
569
- })
570
- s.shutdownChan <- err
571
- }
572
- close(s.shutdownChan)
573
-
574
- return
575
-}
576
-
577
-// Closes spdy connection by sending GoAway frame and initiating shutdown
578
-func (s *Connection) Close() error {
579
- s.receiveIdLock.Lock()
580
- if s.goneAway {
581
- s.receiveIdLock.Unlock()
582
- return nil
583
- }
584
- s.goneAway = true
585
- s.receiveIdLock.Unlock()
586
-
587
- var lastStreamId spdy.StreamId
588
- if s.receivedStreamId > 2 {
589
- lastStreamId = s.receivedStreamId - 2
590
- }
591
-
592
- goAwayFrame := &spdy.GoAwayFrame{
593
- LastGoodStreamId: lastStreamId,
594
- Status: spdy.GoAwayOK,
595
- }
596
-
597
- s.writeLock.Lock()
598
- err := s.framer.WriteFrame(goAwayFrame)
599
- s.writeLock.Unlock()
600
- if err != nil {
601
- return err
602
- }
603
-
604
- go s.shutdown(s.closeTimeout)
605
-
606
- return nil
607
-}
608
-
609
-// CloseWait closes the connection and waits for shutdown
610
-// to finish. Note the underlying network Connection
611
-// is not closed until the end of shutdown.
612
-func (s *Connection) CloseWait() error {
613
- closeErr := s.Close()
614
- if closeErr != nil {
615
- return closeErr
616
- }
617
- shutdownErr, ok := <-s.shutdownChan
618
- if ok {
619
- return shutdownErr
620
- }
621
- return nil
622
-}
623
-
624
-// Wait waits for the connection to finish shutdown or for
625
-// the wait timeout duration to expire. This needs to be
626
-// called either after Close has been called or the GOAWAYFRAME
627
-// has been received. If the wait timeout is 0, this function
628
-// will block until shutdown finishes. If wait is never called
629
-// and a shutdown error occurs, that error will be logged as an
630
-// unhandled error.
631
-func (s *Connection) Wait(waitTimeout time.Duration) error {
632
- var timeout <-chan time.Time
633
- if waitTimeout > time.Duration(0) {
634
- timeout = time.After(waitTimeout)
635
- }
636
-
637
- select {
638
- case err, ok := <-s.shutdownChan:
639
- if ok {
640
- return err
641
- }
642
- case <-timeout:
643
- return ErrTimeout
644
- }
645
- return nil
646
-}
647
-
648
-// NotifyClose registers a channel to be called when the remote
649
-// peer inidicates connection closure. The last stream to be
650
-// received by the remote will be sent on the channel. The notify
651
-// timeout will determine the duration between go away received
652
-// and the connection being closed.
653
-func (s *Connection) NotifyClose(c chan<- *Stream, timeout time.Duration) {
654
- s.goAwayTimeout = timeout
655
- s.lastStreamChan = c
656
-}
657
-
658
-// SetCloseTimeout sets the amount of time close will wait for
659
-// streams to finish before terminating the underlying network
660
-// connection. Setting the timeout to 0 will cause close to
661
-// wait forever, which is the default.
662
-func (s *Connection) SetCloseTimeout(timeout time.Duration) {
663
- s.closeTimeout = timeout
664
-}
665
-
666
-func (s *Connection) sendHeaders(headers http.Header, stream *Stream, fin bool) error {
667
- var flags spdy.ControlFlags
668
- if fin {
669
- flags = spdy.ControlFlagFin
670
- }
671
-
672
- headerFrame := &spdy.HeadersFrame{
673
- StreamId: stream.streamId,
674
- Headers: headers,
675
- CFHeader: spdy.ControlFrameHeader{Flags: flags},
676
- }
677
-
678
- s.writeLock.Lock()
679
- defer s.writeLock.Unlock()
680
- return s.framer.WriteFrame(headerFrame)
681
-}
682
-
683
-func (s *Connection) sendReply(headers http.Header, stream *Stream, fin bool) error {
684
- var flags spdy.ControlFlags
685
- if fin {
686
- flags = spdy.ControlFlagFin
687
- }
688
-
689
- replyFrame := &spdy.SynReplyFrame{
690
- StreamId: stream.streamId,
691
- Headers: headers,
692
- CFHeader: spdy.ControlFrameHeader{Flags: flags},
693
- }
694
-
695
- s.writeLock.Lock()
696
- defer s.writeLock.Unlock()
697
- return s.framer.WriteFrame(replyFrame)
698
-}
699
-
700
-func (s *Connection) sendResetFrame(status spdy.RstStreamStatus, streamId spdy.StreamId) error {
701
- resetFrame := &spdy.RstStreamFrame{
702
- StreamId: streamId,
703
- Status: status,
704
- }
705
-
706
- s.writeLock.Lock()
707
- defer s.writeLock.Unlock()
708
- return s.framer.WriteFrame(resetFrame)
709
-}
710
-
711
-func (s *Connection) sendReset(status spdy.RstStreamStatus, stream *Stream) error {
712
- return s.sendResetFrame(status, stream.streamId)
713
-}
714
-
715
-func (s *Connection) sendStream(stream *Stream, fin bool) error {
716
- var flags spdy.ControlFlags
717
- if fin {
718
- flags = spdy.ControlFlagFin
719
- stream.finished = true
720
- }
721
-
722
- var parentId spdy.StreamId
723
- if stream.parent != nil {
724
- parentId = stream.parent.streamId
725
- }
726
-
727
- streamFrame := &spdy.SynStreamFrame{
728
- StreamId: spdy.StreamId(stream.streamId),
729
- AssociatedToStreamId: spdy.StreamId(parentId),
730
- Headers: stream.headers,
731
- CFHeader: spdy.ControlFrameHeader{Flags: flags},
732
- }
733
-
734
- s.writeLock.Lock()
735
- defer s.writeLock.Unlock()
736
- return s.framer.WriteFrame(streamFrame)
737
-}
738
-
739
-// getNextStreamId returns the next sequential id
740
-// every call should produce a unique value or an error
741
-func (s *Connection) getNextStreamId() spdy.StreamId {
742
- s.nextIdLock.Lock()
743
- defer s.nextIdLock.Unlock()
744
- sid := s.nextStreamId
745
- if sid > 0x7fffffff {
746
- return 0
747
- }
748
- s.nextStreamId = s.nextStreamId + 2
749
- return sid
750
-}
751
-
752
-// PeekNextStreamId returns the next sequential id and keeps the next id untouched
753
-func (s *Connection) PeekNextStreamId() spdy.StreamId {
754
- sid := s.nextStreamId
755
- return sid
756
-}
757
-
758
-func (s *Connection) validateStreamId(rid spdy.StreamId) error {
759
- if rid > 0x7fffffff || rid < s.receivedStreamId {
760
- return ErrInvalidStreamId
761
- }
762
- s.receivedStreamId = rid + 2
763
- return nil
764
-}
765
-
766
-func (s *Connection) addStream(stream *Stream) {
767
- s.streamCond.L.Lock()
768
- s.streams[stream.streamId] = stream
769
- debugMessage("(%p) (%p) Stream added, broadcasting: %d", s, stream, stream.streamId)
770
- s.streamCond.Broadcast()
771
- s.streamCond.L.Unlock()
772
-}
773
-
774
-func (s *Connection) removeStream(stream *Stream) {
775
- s.streamCond.L.Lock()
776
- delete(s.streams, stream.streamId)
777
- debugMessage("Stream removed, broadcasting: %d", stream.streamId)
778
- s.streamCond.Broadcast()
779
- s.streamCond.L.Unlock()
780
-}
781
-
782
-func (s *Connection) getStream(streamId spdy.StreamId) (stream *Stream, ok bool) {
783
- s.streamLock.RLock()
784
- stream, ok = s.streams[streamId]
785
- s.streamLock.RUnlock()
786
- return
787
-}
788
-
789
-// FindStream looks up the given stream id and either waits for the
790
-// stream to be found or returns nil if the stream id is no longer
791
-// valid.
792
-func (s *Connection) FindStream(streamId uint32) *Stream {
793
- var stream *Stream
794
- var ok bool
795
- s.streamCond.L.Lock()
796
- stream, ok = s.streams[spdy.StreamId(streamId)]
797
- debugMessage("(%p) Found stream %d? %t", s, spdy.StreamId(streamId), ok)
798
- for !ok && streamId >= uint32(s.receivedStreamId) {
799
- s.streamCond.Wait()
800
- stream, ok = s.streams[spdy.StreamId(streamId)]
801
- }
802
- s.streamCond.L.Unlock()
803
- return stream
804
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/handlers.go
deleted
-38
@@ -1,38 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "io"
5
- "net/http"
6
-)
7
-
8
-// MirrorStreamHandler mirrors all streams.
9
-func MirrorStreamHandler(stream *Stream) {
10
- replyErr := stream.SendReply(http.Header{}, false)
11
- if replyErr != nil {
12
- return
13
- }
14
-
15
- go func() {
16
- io.Copy(stream, stream)
17
- stream.Close()
18
- }()
19
- go func() {
20
- for {
21
- header, receiveErr := stream.ReceiveHeader()
22
- if receiveErr != nil {
23
- return
24
- }
25
- sendErr := stream.SendHeader(header, false)
26
- if sendErr != nil {
27
- return
28
- }
29
- }
30
- }()
31
-}
32
-
33
-// NoopStreamHandler does nothing when stream connects, most
34
-// likely used with RejectAuthHandler which will not allow any
35
-// streams to make it to the stream handler.
36
-func NoOpStreamHandler(stream *Stream) {
37
- stream.SendReply(http.Header{}, false)
38
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/priority.go
deleted
-97
@@ -1,97 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "container/heap"
5
- "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/spdy"
6
- "sync"
7
-)
8
-
9
-type prioritizedFrame struct {
10
- frame spdy.Frame
11
- priority uint8
12
- insertId uint64
13
-}
14
-
15
-type frameQueue []*prioritizedFrame
16
-
17
-func (fq frameQueue) Len() int {
18
- return len(fq)
19
-}
20
-
21
-func (fq frameQueue) Less(i, j int) bool {
22
- if fq[i].priority == fq[j].priority {
23
- return fq[i].insertId < fq[j].insertId
24
- }
25
- return fq[i].priority < fq[j].priority
26
-}
27
-
28
-func (fq frameQueue) Swap(i, j int) {
29
- fq[i], fq[j] = fq[j], fq[i]
30
-}
31
-
32
-func (fq *frameQueue) Push(x interface{}) {
33
- *fq = append(*fq, x.(*prioritizedFrame))
34
-}
35
-
36
-func (fq *frameQueue) Pop() interface{} {
37
- old := *fq
38
- n := len(old)
39
- *fq = old[0 : n-1]
40
- return old[n-1]
41
-}
42
-
43
-type PriorityFrameQueue struct {
44
- queue *frameQueue
45
- c *sync.Cond
46
- size int
47
- nextInsertId uint64
48
- drain bool
49
-}
50
-
51
-func NewPriorityFrameQueue(size int) *PriorityFrameQueue {
52
- queue := make(frameQueue, 0, size)
53
- heap.Init(&queue)
54
-
55
- return &PriorityFrameQueue{
56
- queue: &queue,
57
- size: size,
58
- c: sync.NewCond(&sync.Mutex{}),
59
- }
60
-}
61
-
62
-func (q *PriorityFrameQueue) Push(frame spdy.Frame, priority uint8) {
63
- q.c.L.Lock()
64
- defer q.c.L.Unlock()
65
- for q.queue.Len() >= q.size {
66
- q.c.Wait()
67
- }
68
- pFrame := &prioritizedFrame{
69
- frame: frame,
70
- priority: priority,
71
- insertId: q.nextInsertId,
72
- }
73
- q.nextInsertId = q.nextInsertId + 1
74
- heap.Push(q.queue, pFrame)
75
- q.c.Signal()
76
-}
77
-
78
-func (q *PriorityFrameQueue) Pop() spdy.Frame {
79
- q.c.L.Lock()
80
- defer q.c.L.Unlock()
81
- for q.queue.Len() == 0 {
82
- if q.drain {
83
- return nil
84
- }
85
- q.c.Wait()
86
- }
87
- frame := heap.Pop(q.queue).(*prioritizedFrame).frame
88
- q.c.Signal()
89
- return frame
90
-}
91
-
92
-func (q *PriorityFrameQueue) Drain() {
93
- q.c.L.Lock()
94
- defer q.c.L.Unlock()
95
- q.drain = true
96
- q.c.Broadcast()
97
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/priority_test.go
deleted
-107
@@ -1,107 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/spdy"
5
- "sync"
6
- "testing"
7
- "time"
8
-)
9
-
10
-func TestPriorityQueueOrdering(t *testing.T) {
11
- queue := NewPriorityFrameQueue(150)
12
- data1 := &spdy.DataFrame{}
13
- data2 := &spdy.DataFrame{}
14
- data3 := &spdy.DataFrame{}
15
- data4 := &spdy.DataFrame{}
16
- queue.Push(data1, 2)
17
- queue.Push(data2, 1)
18
- queue.Push(data3, 1)
19
- queue.Push(data4, 0)
20
-
21
- if queue.Pop() != data4 {
22
- t.Fatalf("Wrong order, expected data4 first")
23
- }
24
- if queue.Pop() != data2 {
25
- t.Fatalf("Wrong order, expected data2 second")
26
- }
27
- if queue.Pop() != data3 {
28
- t.Fatalf("Wrong order, expected data3 third")
29
- }
30
- if queue.Pop() != data1 {
31
- t.Fatalf("Wrong order, expected data1 fourth")
32
- }
33
-
34
- // Insert 50 Medium priority frames
35
- for i := spdy.StreamId(50); i < 100; i++ {
36
- queue.Push(&spdy.DataFrame{StreamId: i}, 1)
37
- }
38
- // Insert 50 low priority frames
39
- for i := spdy.StreamId(100); i < 150; i++ {
40
- queue.Push(&spdy.DataFrame{StreamId: i}, 2)
41
- }
42
- // Insert 50 high priority frames
43
- for i := spdy.StreamId(0); i < 50; i++ {
44
- queue.Push(&spdy.DataFrame{StreamId: i}, 0)
45
- }
46
-
47
- for i := spdy.StreamId(0); i < 150; i++ {
48
- frame := queue.Pop()
49
- if frame.(*spdy.DataFrame).StreamId != i {
50
- t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i)
51
- }
52
- }
53
-}
54
-
55
-func TestPriorityQueueSync(t *testing.T) {
56
- queue := NewPriorityFrameQueue(150)
57
- var wg sync.WaitGroup
58
- insertRange := func(start, stop spdy.StreamId, priority uint8) {
59
- for i := start; i < stop; i++ {
60
- queue.Push(&spdy.DataFrame{StreamId: i}, priority)
61
- }
62
- wg.Done()
63
- }
64
- wg.Add(3)
65
- go insertRange(spdy.StreamId(100), spdy.StreamId(150), 2)
66
- go insertRange(spdy.StreamId(0), spdy.StreamId(50), 0)
67
- go insertRange(spdy.StreamId(50), spdy.StreamId(100), 1)
68
-
69
- wg.Wait()
70
- for i := spdy.StreamId(0); i < 150; i++ {
71
- frame := queue.Pop()
72
- if frame.(*spdy.DataFrame).StreamId != i {
73
- t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i)
74
- }
75
- }
76
-}
77
-
78
-func TestPriorityQueueBlocking(t *testing.T) {
79
- queue := NewPriorityFrameQueue(15)
80
- for i := 0; i < 15; i++ {
81
- queue.Push(&spdy.DataFrame{}, 2)
82
- }
83
- doneChan := make(chan bool)
84
- go func() {
85
- queue.Push(&spdy.DataFrame{}, 2)
86
- close(doneChan)
87
- }()
88
- select {
89
- case <-doneChan:
90
- t.Fatalf("Push succeeded, expected to block")
91
- case <-time.After(time.Millisecond):
92
- break
93
- }
94
-
95
- queue.Pop()
96
-
97
- select {
98
- case <-doneChan:
99
- break
100
- case <-time.After(time.Millisecond):
101
- t.Fatalf("Push should have succeeded, but timeout reached")
102
- }
103
-
104
- for i := 0; i < 15; i++ {
105
- queue.Pop()
106
- }
107
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/spdy_bench_test.go
deleted
-117
@@ -1,117 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "fmt"
5
- "io"
6
- "net"
7
- "net/http"
8
- "sync"
9
- "testing"
10
-)
11
-
12
-const (
13
- LISTEN_ADDRESS = "127.0.0.1:7777"
14
-)
15
-
16
-func configureServer() (io.Closer, *sync.WaitGroup) {
17
- authenticated = true
18
- wg := &sync.WaitGroup{}
19
- server, serverErr := runServer(LISTEN_ADDRESS, wg)
20
-
21
- if serverErr != nil {
22
- panic(serverErr)
23
- }
24
-
25
- return server, wg
26
-}
27
-
28
-func BenchmarkDial10000(b *testing.B) {
29
- server, wg := configureServer()
30
-
31
- defer func() {
32
- server.Close()
33
- wg.Wait()
34
- }()
35
-
36
- for i := 0; i < b.N; i++ {
37
- conn, dialErr := net.Dial("tcp", LISTEN_ADDRESS)
38
- if dialErr != nil {
39
- panic(fmt.Sprintf("Error dialing server: %s", dialErr))
40
- }
41
- conn.Close()
42
- }
43
-}
44
-
45
-func BenchmarkDialWithSPDYStream10000(b *testing.B) {
46
- server, wg := configureServer()
47
-
48
- defer func() {
49
- server.Close()
50
- wg.Wait()
51
- }()
52
-
53
- for i := 0; i < b.N; i++ {
54
- conn, dialErr := net.Dial("tcp", LISTEN_ADDRESS)
55
- if dialErr != nil {
56
- b.Fatalf("Error dialing server: %s", dialErr)
57
- }
58
-
59
- spdyConn, spdyErr := NewConnection(conn, false)
60
- if spdyErr != nil {
61
- b.Fatalf("Error creating spdy connection: %s", spdyErr)
62
- }
63
- go spdyConn.Serve(NoOpStreamHandler)
64
-
65
- closeErr := spdyConn.Close()
66
- if closeErr != nil {
67
- b.Fatalf("Error closing connection: %s, closeErr")
68
- }
69
- }
70
-}
71
-
72
-func benchmarkStreamWithDataAndSize(size uint64, b *testing.B) {
73
- server, wg := configureServer()
74
-
75
- defer func() {
76
- server.Close()
77
- wg.Wait()
78
- }()
79
-
80
- for i := 0; i < b.N; i++ {
81
- conn, dialErr := net.Dial("tcp", LISTEN_ADDRESS)
82
- if dialErr != nil {
83
- b.Fatalf("Error dialing server: %s", dialErr)
84
- }
85
-
86
- spdyConn, spdyErr := NewConnection(conn, false)
87
- if spdyErr != nil {
88
- b.Fatalf("Error creating spdy connection: %s", spdyErr)
89
- }
90
-
91
- go spdyConn.Serve(MirrorStreamHandler)
92
-
93
- stream, err := spdyConn.CreateStream(http.Header{}, nil, false)
94
-
95
- writer := make([]byte, size)
96
-
97
- stream.Write(writer)
98
-
99
- if err != nil {
100
- panic(err)
101
- }
102
-
103
- reader := make([]byte, size)
104
- stream.Read(reader)
105
-
106
- stream.Close()
107
-
108
- closeErr := spdyConn.Close()
109
- if closeErr != nil {
110
- b.Fatalf("Error closing connection: %s, closeErr")
111
- }
112
- }
113
-}
114
-
115
-func BenchmarkStreamWith1Byte10000(b *testing.B) { benchmarkStreamWithDataAndSize(1, b) }
116
-func BenchmarkStreamWith1KiloByte10000(b *testing.B) { benchmarkStreamWithDataAndSize(1024, b) }
117
-func BenchmarkStreamWith1Megabyte10000(b *testing.B) { benchmarkStreamWithDataAndSize(1024*1024, b) }
Godeps/_workspace/src/github.com/jbenet/spdystream/spdy_test.go
deleted
-284
@@ -1,284 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "bytes"
5
- "io"
6
- "net"
7
- "net/http"
8
- "sync"
9
- "testing"
10
- "time"
11
-)
12
-
13
-func TestSpdyStreams(t *testing.T) {
14
- var wg sync.WaitGroup
15
- listen := "localhost:7443"
16
- server, serverErr := runServer(listen, &wg)
17
- if serverErr != nil {
18
- t.Fatalf("Error initializing server: %s", serverErr)
19
- }
20
-
21
- conn, dialErr := net.Dial("tcp", listen)
22
- if dialErr != nil {
23
- t.Fatalf("Error dialing server: %s", dialErr)
24
- }
25
-
26
- spdyConn, spdyErr := NewConnection(conn, false)
27
- if spdyErr != nil {
28
- t.Fatalf("Error creating spdy connection: %s", spdyErr)
29
- }
30
- go spdyConn.Serve(NoOpStreamHandler)
31
-
32
- authenticated = true
33
- stream, streamErr := spdyConn.CreateStream(http.Header{}, nil, false)
34
- if streamErr != nil {
35
- t.Fatalf("Error creating stream: %s", streamErr)
36
- }
37
-
38
- waitErr := stream.Wait()
39
- if waitErr != nil {
40
- t.Fatalf("Error waiting for stream: %s", waitErr)
41
- }
42
-
43
- message := []byte("hello")
44
- writeErr := stream.WriteData(message, false)
45
- if writeErr != nil {
46
- t.Fatalf("Error writing data")
47
- }
48
-
49
- buf := make([]byte, 10)
50
- n, readErr := stream.Read(buf)
51
- if readErr != nil {
52
- t.Fatalf("Error reading data from stream: %s", readErr)
53
- }
54
- if n != 5 {
55
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 5", n)
56
- }
57
- if bytes.Compare(buf[:n], message) != 0 {
58
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", buf, message)
59
- }
60
-
61
- headers := http.Header{
62
- "TestKey": []string{"TestVal"},
63
- }
64
- sendErr := stream.SendHeader(headers, false)
65
- if sendErr != nil {
66
- t.Fatalf("Error sending headers: %s", sendErr)
67
- }
68
- receiveHeaders, receiveErr := stream.ReceiveHeader()
69
- if receiveErr != nil {
70
- t.Fatalf("Error receiving headers: %s", receiveErr)
71
- }
72
- if len(receiveHeaders) != 1 {
73
- t.Fatalf("Unexpected number of headers:\nActual: %d\nExpecting:%d", len(receiveHeaders), 1)
74
- }
75
- testVal := receiveHeaders.Get("TestKey")
76
- if testVal != "TestVal" {
77
- t.Fatalf("Wrong test value:\nActual: %q\nExpecting: %q", testVal, "TestVal")
78
- }
79
-
80
- writeErr = stream.WriteData(message, true)
81
- if writeErr != nil {
82
- t.Fatalf("Error writing data")
83
- }
84
-
85
- smallBuf := make([]byte, 3)
86
- n, readErr = stream.Read(smallBuf)
87
- if readErr != nil {
88
- t.Fatalf("Error reading data from stream: %s", readErr)
89
- }
90
- if n != 3 {
91
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 3", n)
92
- }
93
- if bytes.Compare(smallBuf[:n], []byte("hel")) != 0 {
94
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", smallBuf[:n], message)
95
- }
96
- n, readErr = stream.Read(smallBuf)
97
- if readErr != nil {
98
- t.Fatalf("Error reading data from stream: %s", readErr)
99
- }
100
- if n != 2 {
101
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 2", n)
102
- }
103
- if bytes.Compare(smallBuf[:n], []byte("lo")) != 0 {
104
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpected: lo", smallBuf[:n])
105
- }
106
-
107
- n, readErr = stream.Read(buf)
108
- if readErr != io.EOF {
109
- t.Fatalf("Expected EOF reading from finished stream, read %d bytes", n)
110
- }
111
-
112
- // Closing again should return error since stream is already closed
113
- streamCloseErr := stream.Close()
114
- if streamCloseErr == nil {
115
- t.Fatalf("No error closing finished stream")
116
- }
117
- if streamCloseErr != ErrWriteClosedStream {
118
- t.Fatalf("Unexpected error closing stream: %s", streamCloseErr)
119
- }
120
-
121
- streamResetErr := stream.Reset()
122
- if streamResetErr != nil {
123
- t.Fatalf("Error reseting stream: %s", streamResetErr)
124
- }
125
-
126
- authenticated = false
127
- badStream, badStreamErr := spdyConn.CreateStream(http.Header{}, nil, false)
128
- if badStreamErr != nil {
129
- t.Fatalf("Error creating stream: %s", badStreamErr)
130
- }
131
-
132
- waitErr = badStream.Wait()
133
- if waitErr == nil {
134
- t.Fatalf("Did not receive error creating stream")
135
- }
136
- if waitErr != ErrReset {
137
- t.Fatalf("Unexpected error creating stream: %s", waitErr)
138
- }
139
- streamCloseErr = badStream.Close()
140
- if streamCloseErr == nil {
141
- t.Fatalf("No error closing bad stream")
142
- }
143
-
144
- spdyCloseErr := spdyConn.Close()
145
- if spdyCloseErr != nil {
146
- t.Fatalf("Error closing spdy connection: %s", spdyCloseErr)
147
- }
148
-
149
- closeErr := server.Close()
150
- if closeErr != nil {
151
- t.Fatalf("Error shutting down server: %s", closeErr)
152
- }
153
- wg.Wait()
154
-}
155
-
156
-func TestPing(t *testing.T) {
157
- var wg sync.WaitGroup
158
- listen := "localhost:7543"
159
- server, serverErr := runServer(listen, &wg)
160
- if serverErr != nil {
161
- t.Fatalf("Error initializing server: %s", serverErr)
162
- }
163
-
164
- conn, dialErr := net.Dial("tcp", listen)
165
- if dialErr != nil {
166
- t.Fatalf("Error dialing server: %s", dialErr)
167
- }
168
-
169
- spdyConn, spdyErr := NewConnection(conn, false)
170
- if spdyErr != nil {
171
- t.Fatalf("Error creating spdy connection: %s", spdyErr)
172
- }
173
- go spdyConn.Serve(NoOpStreamHandler)
174
-
175
- pingTime, pingErr := spdyConn.Ping()
176
- if pingErr != nil {
177
- t.Fatalf("Error pinging server: %s", pingErr)
178
- }
179
- if pingTime == time.Duration(0) {
180
- t.Fatalf("Expecting non-zero ping time")
181
- }
182
-
183
- closeErr := server.Close()
184
- if closeErr != nil {
185
- t.Fatalf("Error shutting down server: %s", closeErr)
186
- }
187
- wg.Wait()
188
-}
189
-
190
-func TestHalfClose(t *testing.T) {
191
- var wg sync.WaitGroup
192
- listen := "localhost:7643"
193
- server, serverErr := runServer(listen, &wg)
194
- if serverErr != nil {
195
- t.Fatalf("Error initializing server: %s", serverErr)
196
- }
197
-
198
- conn, dialErr := net.Dial("tcp", listen)
199
- if dialErr != nil {
200
- t.Fatalf("Error dialing server: %s", dialErr)
201
- }
202
-
203
- spdyConn, spdyErr := NewConnection(conn, false)
204
- if spdyErr != nil {
205
- t.Fatalf("Error creating spdy connection: %s", spdyErr)
206
- }
207
- go spdyConn.Serve(NoOpStreamHandler)
208
-
209
- authenticated = true
210
- stream, streamErr := spdyConn.CreateStream(http.Header{}, nil, false)
211
- if streamErr != nil {
212
- t.Fatalf("Error creating stream: %s", streamErr)
213
- }
214
-
215
- waitErr := stream.Wait()
216
- if waitErr != nil {
217
- t.Fatalf("Error waiting for stream: %s", waitErr)
218
- }
219
-
220
- message := []byte("hello and will read after close")
221
- writeErr := stream.WriteData(message, false)
222
- if writeErr != nil {
223
- t.Fatalf("Error writing data")
224
- }
225
-
226
- streamCloseErr := stream.Close()
227
- if streamCloseErr != nil {
228
- t.Fatalf("Error closing stream: %s", streamCloseErr)
229
- }
230
-
231
- buf := make([]byte, 40)
232
- n, readErr := stream.Read(buf)
233
- if readErr != nil {
234
- t.Fatalf("Error reading data from stream: %s", readErr)
235
- }
236
- if n != 31 {
237
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 5", n)
238
- }
239
- if bytes.Compare(buf[:n], message) != 0 {
240
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", buf, message)
241
- }
242
-
243
- spdyCloseErr := spdyConn.Close()
244
- if spdyCloseErr != nil {
245
- t.Fatalf("Error closing spdy connection: %s", spdyCloseErr)
246
- }
247
-
248
- closeErr := server.Close()
249
- if closeErr != nil {
250
- t.Fatalf("Error shutting down server: %s", closeErr)
251
- }
252
- wg.Wait()
253
-}
254
-
255
-var authenticated bool
256
-
257
-func authStreamHandler(stream *Stream) {
258
- if !authenticated {
259
- stream.Refuse()
260
- }
261
- MirrorStreamHandler(stream)
262
-}
263
-
264
-func runServer(listen string, wg *sync.WaitGroup) (io.Closer, error) {
265
- listener, listenErr := net.Listen("tcp", listen)
266
- if listenErr != nil {
267
- return nil, listenErr
268
- }
269
- wg.Add(1)
270
- go func() {
271
- for {
272
- conn, connErr := listener.Accept()
273
- if connErr != nil {
274
- break
275
- }
276
-
277
- spdyConn, _ := NewConnection(conn, true)
278
- go spdyConn.Serve(authStreamHandler)
279
-
280
- }
281
- wg.Done()
282
- }()
283
- return listener, nil
284
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/stream.go
deleted
-334
@@ -1,334 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "errors"
5
- "fmt"
6
- "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/spdy"
7
- "io"
8
- "net"
9
- "net/http"
10
- "sync"
11
- "time"
12
-)
13
-
14
-var (
15
- ErrUnreadPartialData = errors.New("unread partial data")
16
-)
17
-
18
-type Stream struct {
19
- streamId spdy.StreamId
20
- parent *Stream
21
- conn *Connection
22
- startChan chan error
23
-
24
- dataLock sync.RWMutex
25
- dataChan chan []byte
26
- unread []byte
27
-
28
- priority uint8
29
- headers http.Header
30
- headerChan chan http.Header
31
- finishLock sync.Mutex
32
- finished bool
33
- replyCond *sync.Cond
34
- replied bool
35
- closeChan chan bool
36
-
37
- shutdownLock sync.Mutex
38
- shutdownChan chan struct{} // closed when Reset is called (no more R/W).
39
-}
40
-
41
-// WriteData writes data to stream, sending a dataframe per call
42
-func (s *Stream) WriteData(data []byte, fin bool) error {
43
- s.waitWriteReply()
44
- var flags spdy.DataFlags
45
-
46
- if fin {
47
- flags = spdy.DataFlagFin
48
- s.finishLock.Lock()
49
- if s.finished {
50
- s.finishLock.Unlock()
51
- return ErrWriteClosedStream
52
- }
53
- s.finished = true
54
- s.finishLock.Unlock()
55
- }
56
-
57
- dataFrame := &spdy.DataFrame{
58
- StreamId: s.streamId,
59
- Flags: flags,
60
- Data: data,
61
- }
62
-
63
- s.conn.writeLock.Lock()
64
- defer s.conn.writeLock.Unlock()
65
- debugMessage("(%p) (%d) Writing data frame", s, s.streamId)
66
- return s.conn.framer.WriteFrame(dataFrame)
67
-}
68
-
69
-// Write writes bytes to a stream, calling write data for each call.
70
-func (s *Stream) Write(data []byte) (n int, err error) {
71
- err = s.WriteData(data, false)
72
- if err == nil {
73
- n = len(data)
74
- }
75
- return
76
-}
77
-
78
-// Read reads bytes from a stream, a single read will never get more
79
-// than what is sent on a single data frame, but a multiple calls to
80
-// read may get data from the same data frame.
81
-func (s *Stream) Read(p []byte) (n int, err error) {
82
- if s.unread == nil {
83
- select {
84
- case <-s.closeChan:
85
- return 0, io.EOF
86
- case read, ok := <-s.dataChan:
87
- if !ok {
88
- return 0, io.EOF
89
- }
90
- s.unread = read
91
- }
92
- }
93
- n = copy(p, s.unread)
94
- if n < len(s.unread) {
95
- s.unread = s.unread[n:]
96
- } else {
97
- s.unread = nil
98
- }
99
- return
100
-}
101
-
102
-// ReadData reads an entire data frame and returns the byte array
103
-// from the data frame. If there is unread data from the result
104
-// of a Read call, this function will return an ErrUnreadPartialData.
105
-func (s *Stream) ReadData() ([]byte, error) {
106
- debugMessage("(%p) Reading data from %d", s, s.streamId)
107
- if s.unread != nil {
108
- return nil, ErrUnreadPartialData
109
- }
110
- select {
111
- case <-s.closeChan:
112
- return nil, io.EOF
113
- case read, ok := <-s.dataChan:
114
- if !ok {
115
- return nil, io.EOF
116
- }
117
- return read, nil
118
- }
119
-}
120
-
121
-func (s *Stream) waitWriteReply() {
122
- if s.replyCond != nil {
123
- s.replyCond.L.Lock()
124
- for !s.replied {
125
- s.replyCond.Wait()
126
- }
127
- s.replyCond.L.Unlock()
128
- }
129
-}
130
-
131
-// Wait waits for the stream to receive a reply.
132
-func (s *Stream) Wait() error {
133
- return s.WaitTimeout(time.Duration(0))
134
-}
135
-
136
-// WaitTimeout waits for the stream to receive a reply or for timeout.
137
-// When the timeout is reached, ErrTimeout will be returned.
138
-func (s *Stream) WaitTimeout(timeout time.Duration) error {
139
- var timeoutChan <-chan time.Time
140
- if timeout > time.Duration(0) {
141
- timeoutChan = time.After(timeout)
142
- }
143
-
144
- select {
145
- case err := <-s.startChan:
146
- if err != nil {
147
- return err
148
- }
149
- break
150
- case <-timeoutChan:
151
- return ErrTimeout
152
- }
153
- return nil
154
-}
155
-
156
-// Close closes the stream by sending an empty data frame with the
157
-// finish flag set, indicating this side is finished with the stream.
158
-func (s *Stream) Close() error {
159
- select {
160
- case <-s.closeChan:
161
- // Stream is now fully closed
162
- s.conn.removeStream(s)
163
- default:
164
- break
165
- }
166
- return s.WriteData([]byte{}, true)
167
-}
168
-
169
-// Reset sends a reset frame, putting the stream into the fully closed state.
170
-func (s *Stream) Reset() error {
171
- s.conn.removeStream(s)
172
-
173
- // only close it once.
174
- s.shutdownLock.Lock()
175
- select {
176
- case <-s.shutdownChan:
177
- // already was closed.
178
- default:
179
- close(s.shutdownChan)
180
- }
181
- s.shutdownLock.Unlock()
182
-
183
- s.finishLock.Lock()
184
- if s.finished {
185
- s.finishLock.Unlock()
186
- return nil
187
- }
188
- s.finished = true
189
- s.finishLock.Unlock()
190
-
191
- s.dataLock.Lock()
192
- select {
193
- case <-s.closeChan:
194
- break
195
- default:
196
- close(s.dataChan)
197
- close(s.closeChan)
198
- }
199
- s.dataLock.Unlock()
200
-
201
- resetFrame := &spdy.RstStreamFrame{
202
- StreamId: s.streamId,
203
- Status: spdy.Cancel,
204
- }
205
- s.conn.writeLock.Lock()
206
- defer s.conn.writeLock.Unlock()
207
- return s.conn.framer.WriteFrame(resetFrame)
208
-}
209
-
210
-// CreateSubStream creates a stream using the current as the parent
211
-func (s *Stream) CreateSubStream(headers http.Header, fin bool) (*Stream, error) {
212
- return s.conn.CreateStream(headers, s, fin)
213
-}
214
-
215
-// SetPriority sets the stream priority, does not affect the
216
-// remote priority of this stream after Open has been called.
217
-// Valid values are 0 through 7, 0 being the highest priority
218
-// and 7 the lowest.
219
-func (s *Stream) SetPriority(priority uint8) {
220
- s.priority = priority
221
-}
222
-
223
-// SendHeader sends a header frame across the stream
224
-func (s *Stream) SendHeader(headers http.Header, fin bool) error {
225
- return s.conn.sendHeaders(headers, s, fin)
226
-}
227
-
228
-// SendReply sends a reply on a stream, only valid to be called once
229
-// when handling a new stream
230
-func (s *Stream) SendReply(headers http.Header, fin bool) error {
231
- if s.replyCond == nil {
232
- return errors.New("cannot reply on initiated stream")
233
- }
234
- s.replyCond.L.Lock()
235
- defer s.replyCond.L.Unlock()
236
- if s.replied {
237
- return nil
238
- }
239
-
240
- err := s.conn.sendReply(headers, s, fin)
241
- if err != nil {
242
- return err
243
- }
244
-
245
- s.replied = true
246
- s.replyCond.Broadcast()
247
- return nil
248
-}
249
-
250
-// Refuse sends a reset frame with the status refuse, only
251
-// valid to be called once when handling a new stream. This
252
-// may be used to indicate that a stream is not allowed
253
-// when http status codes are not being used.
254
-func (s *Stream) Refuse() error {
255
- if s.replied {
256
- return nil
257
- }
258
- s.replied = true
259
- return s.conn.sendReset(spdy.RefusedStream, s)
260
-}
261
-
262
-// Cancel sends a reset frame with the status canceled. This
263
-// can be used at any time by the creator of the Stream to
264
-// indicate the stream is no longer needed.
265
-func (s *Stream) Cancel() error {
266
- return s.conn.sendReset(spdy.Cancel, s)
267
-}
268
-
269
-// ReceiveHeader receives a header sent on the other side
270
-// of the stream. This function will block until a header
271
-// is received or stream is closed.
272
-func (s *Stream) ReceiveHeader() (http.Header, error) {
273
- select {
274
- case <-s.closeChan:
275
- break
276
- case header, ok := <-s.headerChan:
277
- if !ok {
278
- return nil, fmt.Errorf("header chan closed")
279
- }
280
- return header, nil
281
- }
282
- return nil, fmt.Errorf("stream closed")
283
-}
284
-
285
-// Parent returns the parent stream
286
-func (s *Stream) Parent() *Stream {
287
- return s.parent
288
-}
289
-
290
-// Headers returns the headers used to create the stream
291
-func (s *Stream) Headers() http.Header {
292
- return s.headers
293
-}
294
-
295
-// String returns the string version of stream using the
296
-// streamId to uniquely identify the stream
297
-func (s *Stream) String() string {
298
- return fmt.Sprintf("stream:%d", s.streamId)
299
-}
300
-
301
-// Identifier returns a 32 bit identifier for the stream
302
-func (s *Stream) Identifier() uint32 {
303
- return uint32(s.streamId)
304
-}
305
-
306
-// IsFinished returns whether the stream has finished
307
-// sending data
308
-func (s *Stream) IsFinished() bool {
309
- return s.finished
310
-}
311
-
312
-// Implement net.Conn interface
313
-
314
-func (s *Stream) LocalAddr() net.Addr {
315
- return s.conn.conn.LocalAddr()
316
-}
317
-
318
-func (s *Stream) RemoteAddr() net.Addr {
319
- return s.conn.conn.RemoteAddr()
320
-}
321
-
322
-// TODO set per stream values instead of connection-wide
323
-
324
-func (s *Stream) SetDeadline(t time.Time) error {
325
- return s.conn.conn.SetDeadline(t)
326
-}
327
-
328
-func (s *Stream) SetReadDeadline(t time.Time) error {
329
- return s.conn.conn.SetReadDeadline(t)
330
-}
331
-
332
-func (s *Stream) SetWriteDeadline(t time.Time) error {
333
- return s.conn.conn.SetWriteDeadline(t)
334
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/stream_test.go
deleted
-106
@@ -1,106 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "net"
5
- "net/http"
6
- "sync"
7
- "testing"
8
-)
9
-
10
-func TestStreamReset(t *testing.T) {
11
- var wg sync.WaitGroup
12
- listen := "localhost:7743"
13
- server, serverErr := runServer(listen, &wg)
14
- if serverErr != nil {
15
- t.Fatalf("Error initializing server: %s", serverErr)
16
- }
17
-
18
- conn, dialErr := net.Dial("tcp", listen)
19
- if dialErr != nil {
20
- t.Fatalf("Error dialing server: %s", dialErr)
21
- }
22
-
23
- spdyConn, spdyErr := NewConnection(conn, false)
24
- if spdyErr != nil {
25
- t.Fatalf("Error creating spdy connection: %s", spdyErr)
26
- }
27
- go spdyConn.Serve(NoOpStreamHandler)
28
-
29
- authenticated = true
30
- stream, streamErr := spdyConn.CreateStream(http.Header{}, nil, false)
31
- if streamErr != nil {
32
- t.Fatalf("Error creating stream: %s", streamErr)
33
- }
34
-
35
- buf := []byte("dskjahfkdusahfkdsahfkdsafdkas")
36
- for i := 0; i < 10; i++ {
37
- if _, err := stream.Write(buf); err != nil {
38
- t.Fatalf("Error writing to stream: %s", err)
39
- }
40
- }
41
- for i := 0; i < 10; i++ {
42
- if _, err := stream.Read(buf); err != nil {
43
- t.Fatalf("Error reading from stream: %s", err)
44
- }
45
- }
46
-
47
- // fmt.Printf("Resetting...\n")
48
- if err := stream.Reset(); err != nil {
49
- t.Fatalf("Error reseting stream: %s", err)
50
- }
51
-
52
- closeErr := server.Close()
53
- if closeErr != nil {
54
- t.Fatalf("Error shutting down server: %s", closeErr)
55
- }
56
- wg.Wait()
57
-}
58
-
59
-func TestStreamResetWithDataRemaining(t *testing.T) {
60
- var wg sync.WaitGroup
61
- listen := "localhost:7743"
62
- server, serverErr := runServer(listen, &wg)
63
- if serverErr != nil {
64
- t.Fatalf("Error initializing server: %s", serverErr)
65
- }
66
-
67
- conn, dialErr := net.Dial("tcp", listen)
68
- if dialErr != nil {
69
- t.Fatalf("Error dialing server: %s", dialErr)
70
- }
71
-
72
- spdyConn, spdyErr := NewConnection(conn, false)
73
- if spdyErr != nil {
74
- t.Fatalf("Error creating spdy connection: %s", spdyErr)
75
- }
76
- go spdyConn.Serve(NoOpStreamHandler)
77
-
78
- authenticated = true
79
- stream, streamErr := spdyConn.CreateStream(http.Header{}, nil, false)
80
- if streamErr != nil {
81
- t.Fatalf("Error creating stream: %s", streamErr)
82
- }
83
-
84
- buf := []byte("dskjahfkdusahfkdsahfkdsafdkas")
85
- for i := 0; i < 10; i++ {
86
- if _, err := stream.Write(buf); err != nil {
87
- t.Fatalf("Error writing to stream: %s", err)
88
- }
89
- }
90
-
91
- // read a bit to make sure a goroutine gets to <-dataChan
92
- if _, err := stream.Read(buf); err != nil {
93
- t.Fatalf("Error reading from stream: %s", err)
94
- }
95
-
96
- // fmt.Printf("Resetting...\n")
97
- if err := stream.Reset(); err != nil {
98
- t.Fatalf("Error reseting stream: %s", err)
99
- }
100
-
101
- closeErr := server.Close()
102
- if closeErr != nil {
103
- t.Fatalf("Error shutting down server: %s", closeErr)
104
- }
105
- wg.Wait()
106
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/utils.go
deleted
-16
@@ -1,16 +0,0 @@
1
-package spdystream
2
-
3
-import (
4
- "log"
5
- "os"
6
-)
7
-
8
-var (
9
- DEBUG = os.Getenv("DEBUG")
10
-)
11
-
12
-func debugMessage(fmt string, args ...interface{}) {
13
- if DEBUG != "" {
14
- log.Printf(fmt, args...)
15
- }
16
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/ws/connection.go
deleted
-65
@@ -1,65 +0,0 @@
1
-package ws
2
-
3
-import (
4
- "github.com/gorilla/websocket"
5
- "io"
6
- "log"
7
- "time"
8
-)
9
-
10
-// Wrap an HTTP2 connection over WebSockets and
11
-// use the underlying WebSocket framing for proxy
12
-// compatibility.
13
-type Conn struct {
14
- *websocket.Conn
15
- reader io.Reader
16
-}
17
-
18
-func NewConnection(w *websocket.Conn) *Conn {
19
- return &Conn{Conn: w}
20
-}
21
-
22
-func (c Conn) Write(b []byte) (int, error) {
23
- err := c.WriteMessage(websocket.BinaryMessage, b)
24
- if err != nil {
25
- return 0, err
26
- }
27
- return len(b), nil
28
-}
29
-
30
-func (c Conn) Read(b []byte) (int, error) {
31
- if c.reader == nil {
32
- t, r, err := c.NextReader()
33
- if err != nil {
34
- return 0, err
35
- }
36
- if t != websocket.BinaryMessage {
37
- log.Printf("ws: ignored non-binary message in stream")
38
- return 0, nil
39
- }
40
- c.reader = r
41
- }
42
- n, err := c.reader.Read(b)
43
- if err != nil {
44
- if err == io.EOF {
45
- c.reader = nil
46
- }
47
- return n, err
48
- }
49
- return n, nil
50
-}
51
-
52
-func (c Conn) SetDeadline(t time.Time) error {
53
- if err := c.Conn.SetReadDeadline(t); err != nil {
54
- return err
55
- }
56
- if err := c.Conn.SetWriteDeadline(t); err != nil {
57
- return err
58
- }
59
- return nil
60
-}
61
-
62
-func (c Conn) Close() error {
63
- err := c.Conn.Close()
64
- return err
65
-}
Godeps/_workspace/src/github.com/jbenet/spdystream/ws/ws_test.go
deleted
-175
@@ -1,175 +0,0 @@
1
-package ws
2
-
3
-import (
4
- "bytes"
5
- "github.com/docker/spdystream"
6
- "github.com/gorilla/websocket"
7
- "io"
8
- "log"
9
- "net/http"
10
- "net/http/httptest"
11
- "strings"
12
- "testing"
13
-)
14
-
15
-var upgrader = websocket.Upgrader{
16
- ReadBufferSize: 1024,
17
- WriteBufferSize: 1024,
18
-}
19
-
20
-var serverSpdyConn *spdystream.Connection
21
-
22
-// Connect to the Websocket endpoint at ws://localhost
23
-// using SPDY over Websockets framing.
24
-func ExampleConn() {
25
- wsconn, _, _ := websocket.DefaultDialer.Dial("ws://localhost/", http.Header{"Origin": {"http://localhost/"}})
26
- conn, _ := spdystream.NewConnection(NewConnection(wsconn), false)
27
- go conn.Serve(spdystream.NoOpStreamHandler, spdystream.NoAuthHandler)
28
- stream, _ := conn.CreateStream(http.Header{}, nil, false)
29
- stream.Wait()
30
-}
31
-
32
-func serveWs(w http.ResponseWriter, r *http.Request) {
33
- if r.Method != "GET" {
34
- http.Error(w, "Method not allowed", 405)
35
- return
36
- }
37
-
38
- ws, err := upgrader.Upgrade(w, r, nil)
39
- if err != nil {
40
- if _, ok := err.(websocket.HandshakeError); !ok {
41
- log.Println(err)
42
- }
43
- return
44
- }
45
-
46
- wrap := NewConnection(ws)
47
- spdyConn, err := spdystream.NewConnection(wrap, true)
48
- if err != nil {
49
- log.Fatal(err)
50
- return
51
- }
52
- serverSpdyConn = spdyConn
53
- go spdyConn.Serve(spdystream.MirrorStreamHandler, authStreamHandler)
54
-}
55
-
56
-func TestSpdyStreamOverWs(t *testing.T) {
57
- server := httptest.NewServer(http.HandlerFunc(serveWs))
58
- defer server.Close()
59
- defer func() {
60
- if serverSpdyConn != nil {
61
- serverSpdyConn.Close()
62
- }
63
- }()
64
-
65
- wsconn, _, err := websocket.DefaultDialer.Dial(strings.Replace(server.URL, "http://", "ws://", 1), http.Header{"Origin": {server.URL}})
66
- if err != nil {
67
- t.Fatal(err)
68
- }
69
-
70
- wrap := NewConnection(wsconn)
71
- spdyConn, err := spdystream.NewConnection(wrap, false)
72
- if err != nil {
73
- defer wsconn.Close()
74
- t.Fatal(err)
75
- }
76
- defer spdyConn.Close()
77
- authenticated = true
78
- go spdyConn.Serve(spdystream.NoOpStreamHandler, spdystream.RejectAuthHandler)
79
-
80
- stream, streamErr := spdyConn.CreateStream(http.Header{}, nil, false)
81
- if streamErr != nil {
82
- t.Fatalf("Error creating stream: %s", streamErr)
83
- }
84
-
85
- waitErr := stream.Wait()
86
- if waitErr != nil {
87
- t.Fatalf("Error waiting for stream: %s", waitErr)
88
- }
89
-
90
- message := []byte("hello")
91
- writeErr := stream.WriteData(message, false)
92
- if writeErr != nil {
93
- t.Fatalf("Error writing data")
94
- }
95
-
96
- buf := make([]byte, 10)
97
- n, readErr := stream.Read(buf)
98
- if readErr != nil {
99
- t.Fatalf("Error reading data from stream: %s", readErr)
100
- }
101
- if n != 5 {
102
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 5", n)
103
- }
104
- if bytes.Compare(buf[:n], message) != 0 {
105
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", buf, message)
106
- }
107
-
108
- writeErr = stream.WriteData(message, true)
109
- if writeErr != nil {
110
- t.Fatalf("Error writing data")
111
- }
112
-
113
- smallBuf := make([]byte, 3)
114
- n, readErr = stream.Read(smallBuf)
115
- if readErr != nil {
116
- t.Fatalf("Error reading data from stream: %s", readErr)
117
- }
118
- if n != 3 {
119
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 3", n)
120
- }
121
- if bytes.Compare(smallBuf[:n], []byte("hel")) != 0 {
122
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", smallBuf[:n], message)
123
- }
124
- n, readErr = stream.Read(smallBuf)
125
- if readErr != nil {
126
- t.Fatalf("Error reading data from stream: %s", readErr)
127
- }
128
- if n != 2 {
129
- t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 2", n)
130
- }
131
- if bytes.Compare(smallBuf[:n], []byte("lo")) != 0 {
132
- t.Fatalf("Did not receive expected message:\nActual: %s\nExpected: lo", smallBuf[:n])
133
- }
134
-
135
- n, readErr = stream.Read(buf)
136
- if readErr != io.EOF {
137
- t.Fatalf("Expected EOF reading from finished stream, read %d bytes", n)
138
- }
139
-
140
- streamCloseErr := stream.Close()
141
- if streamCloseErr != nil {
142
- t.Fatalf("Error closing stream: %s", streamCloseErr)
143
- }
144
-
145
- // Closing again should return nil
146
- streamCloseErr = stream.Close()
147
- if streamCloseErr != nil {
148
- t.Fatalf("Error closing stream: %s", streamCloseErr)
149
- }
150
-
151
- authenticated = false
152
- badStream, badStreamErr := spdyConn.CreateStream(http.Header{}, nil, false)
153
- if badStreamErr != nil {
154
- t.Fatalf("Error creating stream: %s", badStreamErr)
155
- }
156
-
157
- waitErr = badStream.Wait()
158
- if waitErr == nil {
159
- t.Fatalf("Did not receive error creating stream")
160
- }
161
- if waitErr != spdystream.ErrReset {
162
- t.Fatalf("Unexpected error creating stream: %s", waitErr)
163
- }
164
-
165
- spdyCloseErr := spdyConn.Close()
166
- if spdyCloseErr != nil {
167
- t.Fatalf("Error closing spdy connection: %s", spdyCloseErr)
168
- }
169
-}
170
-
171
-var authenticated bool
172
-
173
-func authStreamHandler(header http.Header, slot uint8, parent uint32) bool {
174
- return authenticated
175
-}
net/swarm/swarm.go
+4
-2
@@ -10,11 +10,13 @@ import (
10
ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
11
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
12
ps "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream"
13
- psss "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/spdystream"
13
+ psy "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream/transport/yamux"
14
)
15
16
var log = eventlog.Logger("swarm2")
17
18
+var PSTransport = psy.DefaultTransport
19
+
20
// Swarm is a connection muxer, allowing connections to other peers to
21
// be opened and closed, while still using the same Chan for all
22
// communication. The Chan sends/receives Messages, which note the
@@ -35,7 +37,7 @@ func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr,
37
local peer.ID, peers peer.Peerstore) (*Swarm, error) {
38
39
s := &Swarm{
38
- swarm: ps.NewSwarm(psss.Transport),
40
+ swarm: ps.NewSwarm(PSTransport),
41
local: local,
42
peers: peers,
43
cg: ctxgroup.WithContext(ctx),