@cryptotaxi247 / kubo / commits / 8acfcebd6

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