Browse code

Update vendored go.net to use golang.org/x/net canonical path

Signed-off-by: Tibor Vass <tibor@docker.com>

Tibor Vass authored on 2015/06/16 23:08:18
Showing 13 changed files
... ...
@@ -14,8 +14,8 @@ import (
14 14
 	"strings"
15 15
 	"time"
16 16
 
17
-	"code.google.com/p/go.net/websocket"
18 17
 	"github.com/gorilla/mux"
18
+	"golang.org/x/net/websocket"
19 19
 
20 20
 	"github.com/Sirupsen/logrus"
21 21
 	"github.com/docker/docker/api"
... ...
@@ -12,8 +12,9 @@ clone() {
12 12
 	local vcs="$1"
13 13
 	local pkg="$2"
14 14
 	local rev="$3"
15
+	local url="$4"
15 16
 
16
-	local url="https://$pkg"
17
+	: ${url:=https://$pkg}
17 18
 	local target="vendor/src/$pkg"
18 19
 
19 20
 	echo -n "$pkg @ $rev: "
... ...
@@ -2,6 +2,7 @@
2 2
 set -e
3 3
 
4 4
 cd "$(dirname "$BASH_SOURCE")/.."
5
+rm -rf vendor/
5 6
 source 'hack/.vendor-helpers.sh'
6 7
 
7 8
 # the following lines are in sorted order, FYI
... ...
@@ -13,7 +14,7 @@ clone git github.com/gorilla/mux e444e69cbd
13 13
 clone git github.com/kr/pty 5cf931ef8f
14 14
 clone git github.com/mistifyio/go-zfs v2.1.1
15 15
 clone git github.com/tchap/go-patricia v2.1.0
16
-clone hg code.google.com/p/go.net 84a4013f96e0
16
+clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
17 17
 clone hg code.google.com/p/gosqlite 74691fb6f837
18 18
 
19 19
 #get libnetwork packages
... ...
@@ -7,8 +7,7 @@ import (
7 7
 	"time"
8 8
 
9 9
 	"github.com/go-check/check"
10
-
11
-	"code.google.com/p/go.net/websocket"
10
+	"golang.org/x/net/websocket"
12 11
 )
13 12
 
14 13
 func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
15 14
deleted file mode 100644
... ...
@@ -1,112 +0,0 @@
1
-// Copyright 2009 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 websocket
6
-
7
-import (
8
-	"bufio"
9
-	"crypto/tls"
10
-	"io"
11
-	"net"
12
-	"net/http"
13
-	"net/url"
14
-)
15
-
16
-// DialError is an error that occurs while dialling a websocket server.
17
-type DialError struct {
18
-	*Config
19
-	Err error
20
-}
21
-
22
-func (e *DialError) Error() string {
23
-	return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
24
-}
25
-
26
-// NewConfig creates a new WebSocket config for client connection.
27
-func NewConfig(server, origin string) (config *Config, err error) {
28
-	config = new(Config)
29
-	config.Version = ProtocolVersionHybi13
30
-	config.Location, err = url.ParseRequestURI(server)
31
-	if err != nil {
32
-		return
33
-	}
34
-	config.Origin, err = url.ParseRequestURI(origin)
35
-	if err != nil {
36
-		return
37
-	}
38
-	config.Header = http.Header(make(map[string][]string))
39
-	return
40
-}
41
-
42
-// NewClient creates a new WebSocket client connection over rwc.
43
-func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
44
-	br := bufio.NewReader(rwc)
45
-	bw := bufio.NewWriter(rwc)
46
-	switch config.Version {
47
-	case ProtocolVersionHixie75:
48
-		err = hixie75ClientHandshake(config, br, bw)
49
-	case ProtocolVersionHixie76, ProtocolVersionHybi00:
50
-		err = hixie76ClientHandshake(config, br, bw)
51
-	case ProtocolVersionHybi08, ProtocolVersionHybi13:
52
-		err = hybiClientHandshake(config, br, bw)
53
-	default:
54
-		err = ErrBadProtocolVersion
55
-	}
56
-	if err != nil {
57
-		return
58
-	}
59
-	buf := bufio.NewReadWriter(br, bw)
60
-	switch config.Version {
61
-	case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00:
62
-		ws = newHixieClientConn(config, buf, rwc)
63
-	case ProtocolVersionHybi08, ProtocolVersionHybi13:
64
-		ws = newHybiClientConn(config, buf, rwc)
65
-	}
66
-	return
67
-}
68
-
69
-// Dial opens a new client connection to a WebSocket.
70
-func Dial(url_, protocol, origin string) (ws *Conn, err error) {
71
-	config, err := NewConfig(url_, origin)
72
-	if err != nil {
73
-		return nil, err
74
-	}
75
-	if protocol != "" {
76
-		config.Protocol = []string{protocol}
77
-	}
78
-	return DialConfig(config)
79
-}
80
-
81
-// DialConfig opens a new client connection to a WebSocket with a config.
82
-func DialConfig(config *Config) (ws *Conn, err error) {
83
-	var client net.Conn
84
-	if config.Location == nil {
85
-		return nil, &DialError{config, ErrBadWebSocketLocation}
86
-	}
87
-	if config.Origin == nil {
88
-		return nil, &DialError{config, ErrBadWebSocketOrigin}
89
-	}
90
-	switch config.Location.Scheme {
91
-	case "ws":
92
-		client, err = net.Dial("tcp", config.Location.Host)
93
-
94
-	case "wss":
95
-		client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
96
-
97
-	default:
98
-		err = ErrBadScheme
99
-	}
100
-	if err != nil {
101
-		goto Error
102
-	}
103
-
104
-	ws, err = NewClient(config, client)
105
-	if err != nil {
106
-		goto Error
107
-	}
108
-	return
109
-
110
-Error:
111
-	return nil, &DialError{config, err}
112
-}
113 1
deleted file mode 100644
... ...
@@ -1,695 +0,0 @@
1
-// Copyright 2009 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 websocket
6
-
7
-// This file implements a protocol of Hixie draft version 75 and 76
8
-// (draft 76 equals to hybi 00)
9
-
10
-import (
11
-	"bufio"
12
-	"bytes"
13
-	"crypto/md5"
14
-	"encoding/binary"
15
-	"fmt"
16
-	"io"
17
-	"io/ioutil"
18
-	"math/rand"
19
-	"net/http"
20
-	"net/url"
21
-	"strconv"
22
-	"strings"
23
-)
24
-
25
-// An array of characters to be randomly inserted to construct Sec-WebSocket-Key
26
-// value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E.
27
-// See Step 21 in Section 4.1 Opening handshake.
28
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22
29
-var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
30
-
31
-func init() {
32
-	i := 0
33
-	for ch := byte(0x21); ch < 0x30; ch++ {
34
-		secKeyRandomChars[i] = ch
35
-		i++
36
-	}
37
-	for ch := byte(0x3a); ch < 0x7F; ch++ {
38
-		secKeyRandomChars[i] = ch
39
-		i++
40
-	}
41
-}
42
-
43
-type byteReader interface {
44
-	ReadByte() (byte, error)
45
-}
46
-
47
-// readHixieLength reads frame length for frame type 0x80-0xFF
48
-// as defined in Hixie draft.
49
-// See section 4.2 Data framing.
50
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2
51
-func readHixieLength(r byteReader) (length int64, lengthFields []byte, err error) {
52
-	for {
53
-		c, err := r.ReadByte()
54
-		if err != nil {
55
-			return 0, nil, err
56
-		}
57
-		lengthFields = append(lengthFields, c)
58
-		length = length*128 + int64(c&0x7f)
59
-		if c&0x80 == 0 {
60
-			break
61
-		}
62
-	}
63
-	return
64
-}
65
-
66
-// A hixieLengthFrameReader is a reader for frame type 0x80-0xFF
67
-// as defined in hixie draft.
68
-type hixieLengthFrameReader struct {
69
-	reader    io.Reader
70
-	FrameType byte
71
-	Length    int64
72
-	header    *bytes.Buffer
73
-	length    int
74
-}
75
-
76
-func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err error) {
77
-	return frame.reader.Read(msg)
78
-}
79
-
80
-func (frame *hixieLengthFrameReader) PayloadType() byte {
81
-	if frame.FrameType == '\xff' && frame.Length == 0 {
82
-		return CloseFrame
83
-	}
84
-	return UnknownFrame
85
-}
86
-
87
-func (frame *hixieLengthFrameReader) HeaderReader() io.Reader {
88
-	if frame.header == nil {
89
-		return nil
90
-	}
91
-	if frame.header.Len() == 0 {
92
-		frame.header = nil
93
-		return nil
94
-	}
95
-	return frame.header
96
-}
97
-
98
-func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil }
99
-
100
-func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length }
101
-
102
-// A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F
103
-// as defined in hixie draft.
104
-type hixieSentinelFrameReader struct {
105
-	reader      *bufio.Reader
106
-	FrameType   byte
107
-	header      *bytes.Buffer
108
-	data        []byte
109
-	seenTrailer bool
110
-	trailer     *bytes.Buffer
111
-}
112
-
113
-func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err error) {
114
-	if len(frame.data) == 0 {
115
-		if frame.seenTrailer {
116
-			return 0, io.EOF
117
-		}
118
-		frame.data, err = frame.reader.ReadSlice('\xff')
119
-		if err == nil {
120
-			frame.seenTrailer = true
121
-			frame.data = frame.data[:len(frame.data)-1] // trim \xff
122
-			frame.trailer = bytes.NewBuffer([]byte{0xff})
123
-		}
124
-	}
125
-	n = copy(msg, frame.data)
126
-	frame.data = frame.data[n:]
127
-	return n, err
128
-}
129
-
130
-func (frame *hixieSentinelFrameReader) PayloadType() byte {
131
-	if frame.FrameType == 0 {
132
-		return TextFrame
133
-	}
134
-	return UnknownFrame
135
-}
136
-
137
-func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader {
138
-	if frame.header == nil {
139
-		return nil
140
-	}
141
-	if frame.header.Len() == 0 {
142
-		frame.header = nil
143
-		return nil
144
-	}
145
-	return frame.header
146
-}
147
-
148
-func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader {
149
-	if frame.trailer == nil {
150
-		return nil
151
-	}
152
-	if frame.trailer.Len() == 0 {
153
-		frame.trailer = nil
154
-		return nil
155
-	}
156
-	return frame.trailer
157
-}
158
-
159
-func (frame *hixieSentinelFrameReader) Len() int { return -1 }
160
-
161
-// A HixieFrameReaderFactory creates new frame reader based on its frame type.
162
-type hixieFrameReaderFactory struct {
163
-	*bufio.Reader
164
-}
165
-
166
-func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err error) {
167
-	var header []byte
168
-	var b byte
169
-	b, err = buf.ReadByte()
170
-	if err != nil {
171
-		return
172
-	}
173
-	header = append(header, b)
174
-	if b&0x80 == 0x80 {
175
-		length, lengthFields, err := readHixieLength(buf.Reader)
176
-		if err != nil {
177
-			return nil, err
178
-		}
179
-		if length == 0 {
180
-			return nil, io.EOF
181
-		}
182
-		header = append(header, lengthFields...)
183
-		return &hixieLengthFrameReader{
184
-			reader:    io.LimitReader(buf.Reader, length),
185
-			FrameType: b,
186
-			Length:    length,
187
-			header:    bytes.NewBuffer(header)}, err
188
-	}
189
-	return &hixieSentinelFrameReader{
190
-		reader:    buf.Reader,
191
-		FrameType: b,
192
-		header:    bytes.NewBuffer(header)}, err
193
-}
194
-
195
-type hixiFrameWriter struct {
196
-	writer *bufio.Writer
197
-}
198
-
199
-func (frame *hixiFrameWriter) Write(msg []byte) (n int, err error) {
200
-	frame.writer.WriteByte(0)
201
-	frame.writer.Write(msg)
202
-	frame.writer.WriteByte(0xff)
203
-	err = frame.writer.Flush()
204
-	return len(msg), err
205
-}
206
-
207
-func (frame *hixiFrameWriter) Close() error { return nil }
208
-
209
-type hixiFrameWriterFactory struct {
210
-	*bufio.Writer
211
-}
212
-
213
-func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
214
-	if payloadType != TextFrame {
215
-		return nil, ErrNotSupported
216
-	}
217
-	return &hixiFrameWriter{writer: buf.Writer}, nil
218
-}
219
-
220
-type hixiFrameHandler struct {
221
-	conn *Conn
222
-}
223
-
224
-func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
225
-	if header := frame.HeaderReader(); header != nil {
226
-		io.Copy(ioutil.Discard, header)
227
-	}
228
-	if frame.PayloadType() != TextFrame {
229
-		io.Copy(ioutil.Discard, frame)
230
-		return nil, nil
231
-	}
232
-	return frame, nil
233
-}
234
-
235
-func (handler *hixiFrameHandler) WriteClose(_ int) (err error) {
236
-	handler.conn.wio.Lock()
237
-	defer handler.conn.wio.Unlock()
238
-	closingFrame := []byte{'\xff', '\x00'}
239
-	handler.conn.buf.Write(closingFrame)
240
-	return handler.conn.buf.Flush()
241
-}
242
-
243
-// newHixiConn creates a new WebSocket connection speaking hixie draft protocol.
244
-func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
245
-	if buf == nil {
246
-		br := bufio.NewReader(rwc)
247
-		bw := bufio.NewWriter(rwc)
248
-		buf = bufio.NewReadWriter(br, bw)
249
-	}
250
-	ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
251
-		frameReaderFactory: hixieFrameReaderFactory{buf.Reader},
252
-		frameWriterFactory: hixiFrameWriterFactory{buf.Writer},
253
-		PayloadType:        TextFrame}
254
-	ws.frameHandler = &hixiFrameHandler{ws}
255
-	return ws
256
-}
257
-
258
-// getChallengeResponse computes the expected response from the
259
-// challenge as described in section 5.1 Opening Handshake steps 42 to
260
-// 43 of http://www.whatwg.org/specs/web-socket-protocol/
261
-func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err error) {
262
-	// 41. Let /challenge/ be the concatenation of /number_1/, expressed
263
-	// a big-endian 32 bit integer, /number_2/, expressed in a big-
264
-	// endian 32 bit integer, and the eight bytes of /key_3/ in the
265
-	// order they were sent to the wire.
266
-	challenge := make([]byte, 16)
267
-	binary.BigEndian.PutUint32(challenge[0:], number1)
268
-	binary.BigEndian.PutUint32(challenge[4:], number2)
269
-	copy(challenge[8:], key3)
270
-
271
-	// 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
272
-	// endian 128 bit string.
273
-	h := md5.New()
274
-	if _, err = h.Write(challenge); err != nil {
275
-		return
276
-	}
277
-	expected = h.Sum(nil)
278
-	return
279
-}
280
-
281
-// Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
282
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
283
-func generateKeyNumber() (key string, number uint32) {
284
-	// 16.  Let /spaces_n/ be a random integer from 1 to 12 inclusive.
285
-	spaces := rand.Intn(12) + 1
286
-
287
-	// 17. Let /max_n/ be the largest integer not greater than
288
-	//     4,294,967,295 divided by /spaces_n/
289
-	max := int(4294967295 / uint32(spaces))
290
-
291
-	// 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
292
-	number = uint32(rand.Intn(max + 1))
293
-
294
-	// 19. Let /product_n/ be the result of multiplying /number_n/ and
295
-	//     /spaces_n/ together.
296
-	product := number * uint32(spaces)
297
-
298
-	// 20. Let /key_n/ be a string consisting of /product_n/, expressed
299
-	// in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
300
-	// to U+0039 DIGIT NINE (9).
301
-	key = fmt.Sprintf("%d", product)
302
-
303
-	// 21. Insert between one and twelve random characters from the ranges
304
-	//     U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
305
-	//     positions.
306
-	n := rand.Intn(12) + 1
307
-	for i := 0; i < n; i++ {
308
-		pos := rand.Intn(len(key)) + 1
309
-		ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
310
-		key = key[0:pos] + string(ch) + key[pos:]
311
-	}
312
-
313
-	// 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
314
-	//     positions other than the start or end of the string.
315
-	for i := 0; i < spaces; i++ {
316
-		pos := rand.Intn(len(key)-1) + 1
317
-		key = key[0:pos] + " " + key[pos:]
318
-	}
319
-
320
-	return
321
-}
322
-
323
-// Generates handshake key_3 as described in 4.1 Opening handshake step 26.
324
-// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
325
-func generateKey3() (key []byte) {
326
-	// 26. Let /key3/ be a string consisting of eight random bytes (or
327
-	//  equivalently, a random 64 bit integer encoded in big-endian order).
328
-	key = make([]byte, 8)
329
-	for i := 0; i < 8; i++ {
330
-		key[i] = byte(rand.Intn(256))
331
-	}
332
-	return
333
-}
334
-
335
-// Client handshake described in (soon obsolete)
336
-// draft-ietf-hybi-thewebsocket-protocol-00
337
-// (draft-hixie-thewebsocket-protocol-76)
338
-func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
339
-	switch config.Version {
340
-	case ProtocolVersionHixie76, ProtocolVersionHybi00:
341
-	default:
342
-		panic("wrong protocol version.")
343
-	}
344
-	// 4.1. Opening handshake.
345
-	// Step 5.  send a request line.
346
-	bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
347
-
348
-	// Step 6-14. push request headers in fields.
349
-	fields := []string{
350
-		"Upgrade: WebSocket\r\n",
351
-		"Connection: Upgrade\r\n",
352
-		"Host: " + config.Location.Host + "\r\n",
353
-		"Origin: " + config.Origin.String() + "\r\n",
354
-	}
355
-	if len(config.Protocol) > 0 {
356
-		if len(config.Protocol) != 1 {
357
-			return ErrBadWebSocketProtocol
358
-		}
359
-		fields = append(fields, "Sec-WebSocket-Protocol: "+config.Protocol[0]+"\r\n")
360
-	}
361
-	// TODO(ukai): Step 15. send cookie if any.
362
-
363
-	// Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
364
-	key1, number1 := generateKeyNumber()
365
-	key2, number2 := generateKeyNumber()
366
-	if config.handshakeData != nil {
367
-		key1 = config.handshakeData["key1"]
368
-		n, err := strconv.ParseUint(config.handshakeData["number1"], 10, 32)
369
-		if err != nil {
370
-			panic(err)
371
-		}
372
-		number1 = uint32(n)
373
-		key2 = config.handshakeData["key2"]
374
-		n, err = strconv.ParseUint(config.handshakeData["number2"], 10, 32)
375
-		if err != nil {
376
-			panic(err)
377
-		}
378
-		number2 = uint32(n)
379
-	}
380
-	fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n")
381
-	fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n")
382
-
383
-	// Step 24. shuffle fields and send them out.
384
-	for i := 1; i < len(fields); i++ {
385
-		j := rand.Intn(i)
386
-		fields[i], fields[j] = fields[j], fields[i]
387
-	}
388
-	for i := 0; i < len(fields); i++ {
389
-		bw.WriteString(fields[i])
390
-	}
391
-	// Step 25. send CRLF.
392
-	bw.WriteString("\r\n")
393
-
394
-	// Step 26. generate 8 bytes random key.
395
-	key3 := generateKey3()
396
-	if config.handshakeData != nil {
397
-		key3 = []byte(config.handshakeData["key3"])
398
-	}
399
-	// Step 27. send it out.
400
-	bw.Write(key3)
401
-	if err = bw.Flush(); err != nil {
402
-		return
403
-	}
404
-
405
-	// Step 28-29, 32-40. read response from server.
406
-	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
407
-	if err != nil {
408
-		return err
409
-	}
410
-	// Step 30. check response code is 101.
411
-	if resp.StatusCode != 101 {
412
-		return ErrBadStatus
413
-	}
414
-
415
-	// Step 41. check websocket headers.
416
-	if resp.Header.Get("Upgrade") != "WebSocket" ||
417
-		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
418
-		return ErrBadUpgrade
419
-	}
420
-
421
-	if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
422
-		return ErrBadWebSocketOrigin
423
-	}
424
-
425
-	if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
426
-		return ErrBadWebSocketLocation
427
-	}
428
-
429
-	if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
430
-		return ErrBadWebSocketProtocol
431
-	}
432
-
433
-	// Step 42-43. get expected data from challenge data.
434
-	expected, err := getChallengeResponse(number1, number2, key3)
435
-	if err != nil {
436
-		return err
437
-	}
438
-
439
-	// Step 44. read 16 bytes from server.
440
-	reply := make([]byte, 16)
441
-	if _, err = io.ReadFull(br, reply); err != nil {
442
-		return err
443
-	}
444
-
445
-	// Step 45. check the reply equals to expected data.
446
-	if !bytes.Equal(expected, reply) {
447
-		return ErrChallengeResponse
448
-	}
449
-	// WebSocket connection is established.
450
-	return
451
-}
452
-
453
-// Client Handshake described in (soon obsolete)
454
-// draft-hixie-thewebsocket-protocol-75.
455
-func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
456
-	if config.Version != ProtocolVersionHixie75 {
457
-		panic("wrong protocol version.")
458
-	}
459
-	bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
460
-	bw.WriteString("Upgrade: WebSocket\r\n")
461
-	bw.WriteString("Connection: Upgrade\r\n")
462
-	bw.WriteString("Host: " + config.Location.Host + "\r\n")
463
-	bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
464
-	if len(config.Protocol) > 0 {
465
-		if len(config.Protocol) != 1 {
466
-			return ErrBadWebSocketProtocol
467
-		}
468
-		bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
469
-	}
470
-	bw.WriteString("\r\n")
471
-	bw.Flush()
472
-	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
473
-	if err != nil {
474
-		return
475
-	}
476
-	if resp.Status != "101 Web Socket Protocol Handshake" {
477
-		return ErrBadStatus
478
-	}
479
-	if resp.Header.Get("Upgrade") != "WebSocket" ||
480
-		resp.Header.Get("Connection") != "Upgrade" {
481
-		return ErrBadUpgrade
482
-	}
483
-	if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
484
-		return ErrBadWebSocketOrigin
485
-	}
486
-	if resp.Header.Get("Websocket-Location") != config.Location.String() {
487
-		return ErrBadWebSocketLocation
488
-	}
489
-	if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
490
-		return ErrBadWebSocketProtocol
491
-	}
492
-	return
493
-}
494
-
495
-// newHixieClientConn returns new WebSocket connection speaking hixie draft protocol.
496
-func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
497
-	return newHixieConn(config, buf, rwc, nil)
498
-}
499
-
500
-// Gets key number from Sec-WebSocket-Key<n>: field as described
501
-// in 5.2 Sending the server's opening handshake, 4.
502
-func getKeyNumber(s string) (r uint32) {
503
-	// 4. Let /key-number_n/ be the digits (characters in the range
504
-	// U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
505
-	// interpreted as a base ten integer, ignoring all other characters
506
-	// in /key_n/.
507
-	r = 0
508
-	for i := 0; i < len(s); i++ {
509
-		if s[i] >= '0' && s[i] <= '9' {
510
-			r = r*10 + uint32(s[i]) - '0'
511
-		}
512
-	}
513
-	return
514
-}
515
-
516
-// A Hixie76ServerHandshaker performs a server handshake using
517
-// hixie draft 76 protocol.
518
-type hixie76ServerHandshaker struct {
519
-	*Config
520
-	challengeResponse []byte
521
-}
522
-
523
-func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
524
-	c.Version = ProtocolVersionHybi00
525
-	if req.Method != "GET" {
526
-		return http.StatusMethodNotAllowed, ErrBadRequestMethod
527
-	}
528
-	// HTTP version can be safely ignored.
529
-
530
-	if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
531
-		strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
532
-		return http.StatusBadRequest, ErrNotWebSocket
533
-	}
534
-
535
-	// TODO(ukai): check Host
536
-	c.Origin, err = url.ParseRequestURI(req.Header.Get("Origin"))
537
-	if err != nil {
538
-		return http.StatusBadRequest, err
539
-	}
540
-
541
-	key1 := req.Header.Get("Sec-Websocket-Key1")
542
-	if key1 == "" {
543
-		return http.StatusBadRequest, ErrChallengeResponse
544
-	}
545
-	key2 := req.Header.Get("Sec-Websocket-Key2")
546
-	if key2 == "" {
547
-		return http.StatusBadRequest, ErrChallengeResponse
548
-	}
549
-	key3 := make([]byte, 8)
550
-	if _, err := io.ReadFull(buf, key3); err != nil {
551
-		return http.StatusBadRequest, ErrChallengeResponse
552
-	}
553
-
554
-	var scheme string
555
-	if req.TLS != nil {
556
-		scheme = "wss"
557
-	} else {
558
-		scheme = "ws"
559
-	}
560
-	c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
561
-	if err != nil {
562
-		return http.StatusBadRequest, err
563
-	}
564
-
565
-	// Step 4. get key number in Sec-WebSocket-Key<n> fields.
566
-	keyNumber1 := getKeyNumber(key1)
567
-	keyNumber2 := getKeyNumber(key2)
568
-
569
-	// Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
570
-	space1 := uint32(strings.Count(key1, " "))
571
-	space2 := uint32(strings.Count(key2, " "))
572
-	if space1 == 0 || space2 == 0 {
573
-		return http.StatusBadRequest, ErrChallengeResponse
574
-	}
575
-
576
-	// Step 6. key number must be an integral multiple of spaces.
577
-	if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
578
-		return http.StatusBadRequest, ErrChallengeResponse
579
-	}
580
-
581
-	// Step 7. let part be key number divided by spaces.
582
-	part1 := keyNumber1 / space1
583
-	part2 := keyNumber2 / space2
584
-
585
-	// Step 8. let challenge be concatenation of part1, part2 and key3.
586
-	// Step 9. get MD5 fingerprint of challenge.
587
-	c.challengeResponse, err = getChallengeResponse(part1, part2, key3)
588
-	if err != nil {
589
-		return http.StatusInternalServerError, err
590
-	}
591
-	protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
592
-	protocols := strings.Split(protocol, ",")
593
-	for i := 0; i < len(protocols); i++ {
594
-		c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
595
-	}
596
-
597
-	return http.StatusSwitchingProtocols, nil
598
-}
599
-
600
-func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
601
-	if len(c.Protocol) > 0 {
602
-		if len(c.Protocol) != 1 {
603
-			return ErrBadWebSocketProtocol
604
-		}
605
-	}
606
-
607
-	// Step 10. send response status line.
608
-	buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
609
-	// Step 11. send response headers.
610
-	buf.WriteString("Upgrade: WebSocket\r\n")
611
-	buf.WriteString("Connection: Upgrade\r\n")
612
-	buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n")
613
-	buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n")
614
-	if len(c.Protocol) > 0 {
615
-		buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
616
-	}
617
-	// Step 12. send CRLF.
618
-	buf.WriteString("\r\n")
619
-	// Step 13. send response data.
620
-	buf.Write(c.challengeResponse)
621
-	return buf.Flush()
622
-}
623
-
624
-func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
625
-	return newHixieServerConn(c.Config, buf, rwc, request)
626
-}
627
-
628
-// A hixie75ServerHandshaker performs a server handshake using
629
-// hixie draft 75 protocol.
630
-type hixie75ServerHandshaker struct {
631
-	*Config
632
-}
633
-
634
-func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
635
-	c.Version = ProtocolVersionHixie75
636
-	if req.Method != "GET" || req.Proto != "HTTP/1.1" {
637
-		return http.StatusMethodNotAllowed, ErrBadRequestMethod
638
-	}
639
-	if req.Header.Get("Upgrade") != "WebSocket" {
640
-		return http.StatusBadRequest, ErrNotWebSocket
641
-	}
642
-	if req.Header.Get("Connection") != "Upgrade" {
643
-		return http.StatusBadRequest, ErrNotWebSocket
644
-	}
645
-	c.Origin, err = url.ParseRequestURI(strings.TrimSpace(req.Header.Get("Origin")))
646
-	if err != nil {
647
-		return http.StatusBadRequest, err
648
-	}
649
-
650
-	var scheme string
651
-	if req.TLS != nil {
652
-		scheme = "wss"
653
-	} else {
654
-		scheme = "ws"
655
-	}
656
-	c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
657
-	if err != nil {
658
-		return http.StatusBadRequest, err
659
-	}
660
-	protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
661
-	protocols := strings.Split(protocol, ",")
662
-	for i := 0; i < len(protocols); i++ {
663
-		c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
664
-	}
665
-
666
-	return http.StatusSwitchingProtocols, nil
667
-}
668
-
669
-func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
670
-	if len(c.Protocol) > 0 {
671
-		if len(c.Protocol) != 1 {
672
-			return ErrBadWebSocketProtocol
673
-		}
674
-	}
675
-
676
-	buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
677
-	buf.WriteString("Upgrade: WebSocket\r\n")
678
-	buf.WriteString("Connection: Upgrade\r\n")
679
-	buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n")
680
-	buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n")
681
-	if len(c.Protocol) > 0 {
682
-		buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
683
-	}
684
-	buf.WriteString("\r\n")
685
-	return buf.Flush()
686
-}
687
-
688
-func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
689
-	return newHixieServerConn(c.Config, buf, rwc, request)
690
-}
691
-
692
-// newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol.
693
-func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
694
-	return newHixieConn(config, buf, rwc, request)
695
-}
696 1
deleted file mode 100644
... ...
@@ -1,580 +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 websocket
6
-
7
-// This file implements a protocol of hybi draft.
8
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
9
-
10
-import (
11
-	"bufio"
12
-	"bytes"
13
-	"crypto/rand"
14
-	"crypto/sha1"
15
-	"encoding/base64"
16
-	"encoding/binary"
17
-	"fmt"
18
-	"io"
19
-	"io/ioutil"
20
-	"net/http"
21
-	"net/url"
22
-	"strings"
23
-)
24
-
25
-const (
26
-	websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
27
-
28
-	closeStatusNormal            = 1000
29
-	closeStatusGoingAway         = 1001
30
-	closeStatusProtocolError     = 1002
31
-	closeStatusUnsupportedData   = 1003
32
-	closeStatusFrameTooLarge     = 1004
33
-	closeStatusNoStatusRcvd      = 1005
34
-	closeStatusAbnormalClosure   = 1006
35
-	closeStatusBadMessageData    = 1007
36
-	closeStatusPolicyViolation   = 1008
37
-	closeStatusTooBigData        = 1009
38
-	closeStatusExtensionMismatch = 1010
39
-
40
-	maxControlFramePayloadLength = 125
41
-)
42
-
43
-var (
44
-	ErrBadMaskingKey         = &ProtocolError{"bad masking key"}
45
-	ErrBadPongMessage        = &ProtocolError{"bad pong message"}
46
-	ErrBadClosingStatus      = &ProtocolError{"bad closing status"}
47
-	ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
48
-	ErrNotImplemented        = &ProtocolError{"not implemented"}
49
-
50
-	handshakeHeader = map[string]bool{
51
-		"Host":                   true,
52
-		"Upgrade":                true,
53
-		"Connection":             true,
54
-		"Sec-Websocket-Key":      true,
55
-		"Sec-Websocket-Origin":   true,
56
-		"Sec-Websocket-Version":  true,
57
-		"Sec-Websocket-Protocol": true,
58
-		"Sec-Websocket-Accept":   true,
59
-	}
60
-)
61
-
62
-// A hybiFrameHeader is a frame header as defined in hybi draft.
63
-type hybiFrameHeader struct {
64
-	Fin        bool
65
-	Rsv        [3]bool
66
-	OpCode     byte
67
-	Length     int64
68
-	MaskingKey []byte
69
-
70
-	data *bytes.Buffer
71
-}
72
-
73
-// A hybiFrameReader is a reader for hybi frame.
74
-type hybiFrameReader struct {
75
-	reader io.Reader
76
-
77
-	header hybiFrameHeader
78
-	pos    int64
79
-	length int
80
-}
81
-
82
-func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
83
-	n, err = frame.reader.Read(msg)
84
-	if err != nil {
85
-		return 0, err
86
-	}
87
-	if frame.header.MaskingKey != nil {
88
-		for i := 0; i < n; i++ {
89
-			msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
90
-			frame.pos++
91
-		}
92
-	}
93
-	return n, err
94
-}
95
-
96
-func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
97
-
98
-func (frame *hybiFrameReader) HeaderReader() io.Reader {
99
-	if frame.header.data == nil {
100
-		return nil
101
-	}
102
-	if frame.header.data.Len() == 0 {
103
-		return nil
104
-	}
105
-	return frame.header.data
106
-}
107
-
108
-func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
109
-
110
-func (frame *hybiFrameReader) Len() (n int) { return frame.length }
111
-
112
-// A hybiFrameReaderFactory creates new frame reader based on its frame type.
113
-type hybiFrameReaderFactory struct {
114
-	*bufio.Reader
115
-}
116
-
117
-// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
118
-// See Section 5.2 Base Framing protocol for detail.
119
-// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
120
-func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
121
-	hybiFrame := new(hybiFrameReader)
122
-	frame = hybiFrame
123
-	var header []byte
124
-	var b byte
125
-	// First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
126
-	b, err = buf.ReadByte()
127
-	if err != nil {
128
-		return
129
-	}
130
-	header = append(header, b)
131
-	hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
132
-	for i := 0; i < 3; i++ {
133
-		j := uint(6 - i)
134
-		hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
135
-	}
136
-	hybiFrame.header.OpCode = header[0] & 0x0f
137
-
138
-	// Second byte. Mask/Payload len(7bits)
139
-	b, err = buf.ReadByte()
140
-	if err != nil {
141
-		return
142
-	}
143
-	header = append(header, b)
144
-	mask := (b & 0x80) != 0
145
-	b &= 0x7f
146
-	lengthFields := 0
147
-	switch {
148
-	case b <= 125: // Payload length 7bits.
149
-		hybiFrame.header.Length = int64(b)
150
-	case b == 126: // Payload length 7+16bits
151
-		lengthFields = 2
152
-	case b == 127: // Payload length 7+64bits
153
-		lengthFields = 8
154
-	}
155
-	for i := 0; i < lengthFields; i++ {
156
-		b, err = buf.ReadByte()
157
-		if err != nil {
158
-			return
159
-		}
160
-		header = append(header, b)
161
-		hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
162
-	}
163
-	if mask {
164
-		// Masking key. 4 bytes.
165
-		for i := 0; i < 4; i++ {
166
-			b, err = buf.ReadByte()
167
-			if err != nil {
168
-				return
169
-			}
170
-			header = append(header, b)
171
-			hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
172
-		}
173
-	}
174
-	hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
175
-	hybiFrame.header.data = bytes.NewBuffer(header)
176
-	hybiFrame.length = len(header) + int(hybiFrame.header.Length)
177
-	return
178
-}
179
-
180
-// A HybiFrameWriter is a writer for hybi frame.
181
-type hybiFrameWriter struct {
182
-	writer *bufio.Writer
183
-
184
-	header *hybiFrameHeader
185
-}
186
-
187
-func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
188
-	var header []byte
189
-	var b byte
190
-	if frame.header.Fin {
191
-		b |= 0x80
192
-	}
193
-	for i := 0; i < 3; i++ {
194
-		if frame.header.Rsv[i] {
195
-			j := uint(6 - i)
196
-			b |= 1 << j
197
-		}
198
-	}
199
-	b |= frame.header.OpCode
200
-	header = append(header, b)
201
-	if frame.header.MaskingKey != nil {
202
-		b = 0x80
203
-	} else {
204
-		b = 0
205
-	}
206
-	lengthFields := 0
207
-	length := len(msg)
208
-	switch {
209
-	case length <= 125:
210
-		b |= byte(length)
211
-	case length < 65536:
212
-		b |= 126
213
-		lengthFields = 2
214
-	default:
215
-		b |= 127
216
-		lengthFields = 8
217
-	}
218
-	header = append(header, b)
219
-	for i := 0; i < lengthFields; i++ {
220
-		j := uint((lengthFields - i - 1) * 8)
221
-		b = byte((length >> j) & 0xff)
222
-		header = append(header, b)
223
-	}
224
-	if frame.header.MaskingKey != nil {
225
-		if len(frame.header.MaskingKey) != 4 {
226
-			return 0, ErrBadMaskingKey
227
-		}
228
-		header = append(header, frame.header.MaskingKey...)
229
-		frame.writer.Write(header)
230
-		data := make([]byte, length)
231
-		for i := range data {
232
-			data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
233
-		}
234
-		frame.writer.Write(data)
235
-		err = frame.writer.Flush()
236
-		return length, err
237
-	}
238
-	frame.writer.Write(header)
239
-	frame.writer.Write(msg)
240
-	err = frame.writer.Flush()
241
-	return length, err
242
-}
243
-
244
-func (frame *hybiFrameWriter) Close() error { return nil }
245
-
246
-type hybiFrameWriterFactory struct {
247
-	*bufio.Writer
248
-	needMaskingKey bool
249
-}
250
-
251
-func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
252
-	frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
253
-	if buf.needMaskingKey {
254
-		frameHeader.MaskingKey, err = generateMaskingKey()
255
-		if err != nil {
256
-			return nil, err
257
-		}
258
-	}
259
-	return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
260
-}
261
-
262
-type hybiFrameHandler struct {
263
-	conn        *Conn
264
-	payloadType byte
265
-}
266
-
267
-func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
268
-	if handler.conn.IsServerConn() {
269
-		// The client MUST mask all frames sent to the server.
270
-		if frame.(*hybiFrameReader).header.MaskingKey == nil {
271
-			handler.WriteClose(closeStatusProtocolError)
272
-			return nil, io.EOF
273
-		}
274
-	} else {
275
-		// The server MUST NOT mask all frames.
276
-		if frame.(*hybiFrameReader).header.MaskingKey != nil {
277
-			handler.WriteClose(closeStatusProtocolError)
278
-			return nil, io.EOF
279
-		}
280
-	}
281
-	if header := frame.HeaderReader(); header != nil {
282
-		io.Copy(ioutil.Discard, header)
283
-	}
284
-	switch frame.PayloadType() {
285
-	case ContinuationFrame:
286
-		frame.(*hybiFrameReader).header.OpCode = handler.payloadType
287
-	case TextFrame, BinaryFrame:
288
-		handler.payloadType = frame.PayloadType()
289
-	case CloseFrame:
290
-		return nil, io.EOF
291
-	case PingFrame:
292
-		pingMsg := make([]byte, maxControlFramePayloadLength)
293
-		n, err := io.ReadFull(frame, pingMsg)
294
-		if err != nil && err != io.ErrUnexpectedEOF {
295
-			return nil, err
296
-		}
297
-		io.Copy(ioutil.Discard, frame)
298
-		n, err = handler.WritePong(pingMsg[:n])
299
-		if err != nil {
300
-			return nil, err
301
-		}
302
-		return nil, nil
303
-	case PongFrame:
304
-		return nil, ErrNotImplemented
305
-	}
306
-	return frame, nil
307
-}
308
-
309
-func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
310
-	handler.conn.wio.Lock()
311
-	defer handler.conn.wio.Unlock()
312
-	w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
313
-	if err != nil {
314
-		return err
315
-	}
316
-	msg := make([]byte, 2)
317
-	binary.BigEndian.PutUint16(msg, uint16(status))
318
-	_, err = w.Write(msg)
319
-	w.Close()
320
-	return err
321
-}
322
-
323
-func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
324
-	handler.conn.wio.Lock()
325
-	defer handler.conn.wio.Unlock()
326
-	w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
327
-	if err != nil {
328
-		return 0, err
329
-	}
330
-	n, err = w.Write(msg)
331
-	w.Close()
332
-	return n, err
333
-}
334
-
335
-// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
336
-func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
337
-	if buf == nil {
338
-		br := bufio.NewReader(rwc)
339
-		bw := bufio.NewWriter(rwc)
340
-		buf = bufio.NewReadWriter(br, bw)
341
-	}
342
-	ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
343
-		frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
344
-		frameWriterFactory: hybiFrameWriterFactory{
345
-			buf.Writer, request == nil},
346
-		PayloadType:        TextFrame,
347
-		defaultCloseStatus: closeStatusNormal}
348
-	ws.frameHandler = &hybiFrameHandler{conn: ws}
349
-	return ws
350
-}
351
-
352
-// generateMaskingKey generates a masking key for a frame.
353
-func generateMaskingKey() (maskingKey []byte, err error) {
354
-	maskingKey = make([]byte, 4)
355
-	if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
356
-		return
357
-	}
358
-	return
359
-}
360
-
361
-// generateNonce generates a nonce consisting of a randomly selected 16-byte
362
-// value that has been base64-encoded.
363
-func generateNonce() (nonce []byte) {
364
-	key := make([]byte, 16)
365
-	if _, err := io.ReadFull(rand.Reader, key); err != nil {
366
-		panic(err)
367
-	}
368
-	nonce = make([]byte, 24)
369
-	base64.StdEncoding.Encode(nonce, key)
370
-	return
371
-}
372
-
373
-// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
374
-// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
375
-func getNonceAccept(nonce []byte) (expected []byte, err error) {
376
-	h := sha1.New()
377
-	if _, err = h.Write(nonce); err != nil {
378
-		return
379
-	}
380
-	if _, err = h.Write([]byte(websocketGUID)); err != nil {
381
-		return
382
-	}
383
-	expected = make([]byte, 28)
384
-	base64.StdEncoding.Encode(expected, h.Sum(nil))
385
-	return
386
-}
387
-
388
-func isHybiVersion(version int) bool {
389
-	switch version {
390
-	case ProtocolVersionHybi08, ProtocolVersionHybi13:
391
-		return true
392
-	default:
393
-	}
394
-	return false
395
-}
396
-
397
-// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
398
-func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
399
-	if !isHybiVersion(config.Version) {
400
-		panic("wrong protocol version.")
401
-	}
402
-
403
-	bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
404
-
405
-	bw.WriteString("Host: " + config.Location.Host + "\r\n")
406
-	bw.WriteString("Upgrade: websocket\r\n")
407
-	bw.WriteString("Connection: Upgrade\r\n")
408
-	nonce := generateNonce()
409
-	if config.handshakeData != nil {
410
-		nonce = []byte(config.handshakeData["key"])
411
-	}
412
-	bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
413
-	if config.Version == ProtocolVersionHybi13 {
414
-		bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
415
-	} else if config.Version == ProtocolVersionHybi08 {
416
-		bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
417
-	}
418
-	bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
419
-	if len(config.Protocol) > 0 {
420
-		bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
421
-	}
422
-	// TODO(ukai): send Sec-WebSocket-Extensions.
423
-	err = config.Header.WriteSubset(bw, handshakeHeader)
424
-	if err != nil {
425
-		return err
426
-	}
427
-
428
-	bw.WriteString("\r\n")
429
-	if err = bw.Flush(); err != nil {
430
-		return err
431
-	}
432
-
433
-	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
434
-	if err != nil {
435
-		return err
436
-	}
437
-	if resp.StatusCode != 101 {
438
-		return ErrBadStatus
439
-	}
440
-	if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
441
-		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
442
-		return ErrBadUpgrade
443
-	}
444
-	expectedAccept, err := getNonceAccept(nonce)
445
-	if err != nil {
446
-		return err
447
-	}
448
-	if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
449
-		return ErrChallengeResponse
450
-	}
451
-	if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
452
-		return ErrUnsupportedExtensions
453
-	}
454
-	offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
455
-	if offeredProtocol != "" {
456
-		protocolMatched := false
457
-		for i := 0; i < len(config.Protocol); i++ {
458
-			if config.Protocol[i] == offeredProtocol {
459
-				protocolMatched = true
460
-				break
461
-			}
462
-		}
463
-		if !protocolMatched {
464
-			return ErrBadWebSocketProtocol
465
-		}
466
-		config.Protocol = []string{offeredProtocol}
467
-	}
468
-
469
-	return nil
470
-}
471
-
472
-// newHybiClientConn creates a client WebSocket connection after handshake.
473
-func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
474
-	return newHybiConn(config, buf, rwc, nil)
475
-}
476
-
477
-// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
478
-type hybiServerHandshaker struct {
479
-	*Config
480
-	accept []byte
481
-}
482
-
483
-func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
484
-	c.Version = ProtocolVersionHybi13
485
-	if req.Method != "GET" {
486
-		return http.StatusMethodNotAllowed, ErrBadRequestMethod
487
-	}
488
-	// HTTP version can be safely ignored.
489
-
490
-	if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
491
-		!strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
492
-		return http.StatusBadRequest, ErrNotWebSocket
493
-	}
494
-
495
-	key := req.Header.Get("Sec-Websocket-Key")
496
-	if key == "" {
497
-		return http.StatusBadRequest, ErrChallengeResponse
498
-	}
499
-	version := req.Header.Get("Sec-Websocket-Version")
500
-	switch version {
501
-	case "13":
502
-		c.Version = ProtocolVersionHybi13
503
-	case "8":
504
-		c.Version = ProtocolVersionHybi08
505
-	default:
506
-		return http.StatusBadRequest, ErrBadWebSocketVersion
507
-	}
508
-	var scheme string
509
-	if req.TLS != nil {
510
-		scheme = "wss"
511
-	} else {
512
-		scheme = "ws"
513
-	}
514
-	c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
515
-	if err != nil {
516
-		return http.StatusBadRequest, err
517
-	}
518
-	protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
519
-	if protocol != "" {
520
-		protocols := strings.Split(protocol, ",")
521
-		for i := 0; i < len(protocols); i++ {
522
-			c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
523
-		}
524
-	}
525
-	c.accept, err = getNonceAccept([]byte(key))
526
-	if err != nil {
527
-		return http.StatusInternalServerError, err
528
-	}
529
-	return http.StatusSwitchingProtocols, nil
530
-}
531
-
532
-// Origin parses Origin header in "req".
533
-// If origin is "null", returns (nil, nil).
534
-func Origin(config *Config, req *http.Request) (*url.URL, error) {
535
-	var origin string
536
-	switch config.Version {
537
-	case ProtocolVersionHybi13:
538
-		origin = req.Header.Get("Origin")
539
-	case ProtocolVersionHybi08:
540
-		origin = req.Header.Get("Sec-Websocket-Origin")
541
-	}
542
-	if origin == "null" {
543
-		return nil, nil
544
-	}
545
-	return url.ParseRequestURI(origin)
546
-}
547
-
548
-func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
549
-	if len(c.Protocol) > 0 {
550
-		if len(c.Protocol) != 1 {
551
-			// You need choose a Protocol in Handshake func in Server.
552
-			return ErrBadWebSocketProtocol
553
-		}
554
-	}
555
-	buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
556
-	buf.WriteString("Upgrade: websocket\r\n")
557
-	buf.WriteString("Connection: Upgrade\r\n")
558
-	buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
559
-	if len(c.Protocol) > 0 {
560
-		buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
561
-	}
562
-	// TODO(ukai): send Sec-WebSocket-Extensions.
563
-	if c.Header != nil {
564
-		err := c.Header.WriteSubset(buf, handshakeHeader)
565
-		if err != nil {
566
-			return err
567
-		}
568
-	}
569
-	buf.WriteString("\r\n")
570
-	return buf.Flush()
571
-}
572
-
573
-func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
574
-	return newHybiServerConn(c.Config, buf, rwc, request)
575
-}
576
-
577
-// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
578
-func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
579
-	return newHybiConn(config, buf, rwc, request)
580
-}
581 1
deleted file mode 100644
... ...
@@ -1,122 +0,0 @@
1
-// Copyright 2009 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 websocket
6
-
7
-import (
8
-	"bufio"
9
-	"fmt"
10
-	"io"
11
-	"net/http"
12
-)
13
-
14
-func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
15
-	var hs serverHandshaker = &hybiServerHandshaker{Config: config}
16
-	code, err := hs.ReadHandshake(buf.Reader, req)
17
-	if err == ErrBadWebSocketVersion {
18
-		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
19
-		fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
20
-		buf.WriteString("\r\n")
21
-		buf.WriteString(err.Error())
22
-		buf.Flush()
23
-		return
24
-	}
25
-	if err != nil {
26
-		hs = &hixie76ServerHandshaker{Config: config}
27
-		code, err = hs.ReadHandshake(buf.Reader, req)
28
-	}
29
-	if err != nil {
30
-		hs = &hixie75ServerHandshaker{Config: config}
31
-		code, err = hs.ReadHandshake(buf.Reader, req)
32
-	}
33
-	if err != nil {
34
-		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
35
-		buf.WriteString("\r\n")
36
-		buf.WriteString(err.Error())
37
-		buf.Flush()
38
-		return
39
-	}
40
-	if handshake != nil {
41
-		err = handshake(config, req)
42
-		if err != nil {
43
-			code = http.StatusForbidden
44
-			fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
45
-			buf.WriteString("\r\n")
46
-			buf.Flush()
47
-			return
48
-		}
49
-	}
50
-	err = hs.AcceptHandshake(buf.Writer)
51
-	if err != nil {
52
-		code = http.StatusBadRequest
53
-		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
54
-		buf.WriteString("\r\n")
55
-		buf.Flush()
56
-		return
57
-	}
58
-	conn = hs.NewServerConn(buf, rwc, req)
59
-	return
60
-}
61
-
62
-// Server represents a server of a WebSocket.
63
-type Server struct {
64
-	// Config is a WebSocket configuration for new WebSocket connection.
65
-	Config
66
-
67
-	// Handshake is an optional function in WebSocket handshake.
68
-	// For example, you can check, or don't check Origin header.
69
-	// Another example, you can select config.Protocol.
70
-	Handshake func(*Config, *http.Request) error
71
-
72
-	// Handler handles a WebSocket connection.
73
-	Handler
74
-}
75
-
76
-// ServeHTTP implements the http.Handler interface for a WebSocket
77
-func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
78
-	s.serveWebSocket(w, req)
79
-}
80
-
81
-func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
82
-	rwc, buf, err := w.(http.Hijacker).Hijack()
83
-	if err != nil {
84
-		panic("Hijack failed: " + err.Error())
85
-		return
86
-	}
87
-	// The server should abort the WebSocket connection if it finds
88
-	// the client did not send a handshake that matches with protocol
89
-	// specification.
90
-	defer rwc.Close()
91
-	conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
92
-	if err != nil {
93
-		return
94
-	}
95
-	if conn == nil {
96
-		panic("unexpected nil conn")
97
-	}
98
-	s.Handler(conn)
99
-}
100
-
101
-// Handler is a simple interface to a WebSocket browser client.
102
-// It checks if Origin header is valid URL by default.
103
-// You might want to verify websocket.Conn.Config().Origin in the func.
104
-// If you use Server instead of Handler, you could call websocket.Origin and
105
-// check the origin in your Handshake func. So, if you want to accept
106
-// non-browser client, which doesn't send Origin header, you could use Server
107
-//. that doesn't check origin in its Handshake.
108
-type Handler func(*Conn)
109
-
110
-func checkOrigin(config *Config, req *http.Request) (err error) {
111
-	config.Origin, err = Origin(config, req)
112
-	if err == nil && config.Origin == nil {
113
-		return fmt.Errorf("null origin")
114
-	}
115
-	return err
116
-}
117
-
118
-// ServeHTTP implements the http.Handler interface for a WebSocket
119
-func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
120
-	s := Server{Handler: h, Handshake: checkOrigin}
121
-	s.serveWebSocket(w, req)
122
-}
123 1
deleted file mode 100644
... ...
@@ -1,415 +0,0 @@
1
-// Copyright 2009 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 websocket implements a client and server for the WebSocket protocol
6
-// as specified in RFC 6455.
7
-package websocket
8
-
9
-import (
10
-	"bufio"
11
-	"crypto/tls"
12
-	"encoding/json"
13
-	"errors"
14
-	"io"
15
-	"io/ioutil"
16
-	"net"
17
-	"net/http"
18
-	"net/url"
19
-	"sync"
20
-	"time"
21
-)
22
-
23
-const (
24
-	ProtocolVersionHixie75   = -75
25
-	ProtocolVersionHixie76   = -76
26
-	ProtocolVersionHybi00    = 0
27
-	ProtocolVersionHybi08    = 8
28
-	ProtocolVersionHybi13    = 13
29
-	ProtocolVersionHybi      = ProtocolVersionHybi13
30
-	SupportedProtocolVersion = "13, 8"
31
-
32
-	ContinuationFrame = 0
33
-	TextFrame         = 1
34
-	BinaryFrame       = 2
35
-	CloseFrame        = 8
36
-	PingFrame         = 9
37
-	PongFrame         = 10
38
-	UnknownFrame      = 255
39
-)
40
-
41
-// ProtocolError represents WebSocket protocol errors.
42
-type ProtocolError struct {
43
-	ErrorString string
44
-}
45
-
46
-func (err *ProtocolError) Error() string { return err.ErrorString }
47
-
48
-var (
49
-	ErrBadProtocolVersion   = &ProtocolError{"bad protocol version"}
50
-	ErrBadScheme            = &ProtocolError{"bad scheme"}
51
-	ErrBadStatus            = &ProtocolError{"bad status"}
52
-	ErrBadUpgrade           = &ProtocolError{"missing or bad upgrade"}
53
-	ErrBadWebSocketOrigin   = &ProtocolError{"missing or bad WebSocket-Origin"}
54
-	ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
55
-	ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
56
-	ErrBadWebSocketVersion  = &ProtocolError{"missing or bad WebSocket Version"}
57
-	ErrChallengeResponse    = &ProtocolError{"mismatch challenge/response"}
58
-	ErrBadFrame             = &ProtocolError{"bad frame"}
59
-	ErrBadFrameBoundary     = &ProtocolError{"not on frame boundary"}
60
-	ErrNotWebSocket         = &ProtocolError{"not websocket protocol"}
61
-	ErrBadRequestMethod     = &ProtocolError{"bad method"}
62
-	ErrNotSupported         = &ProtocolError{"not supported"}
63
-)
64
-
65
-// Addr is an implementation of net.Addr for WebSocket.
66
-type Addr struct {
67
-	*url.URL
68
-}
69
-
70
-// Network returns the network type for a WebSocket, "websocket".
71
-func (addr *Addr) Network() string { return "websocket" }
72
-
73
-// Config is a WebSocket configuration
74
-type Config struct {
75
-	// A WebSocket server address.
76
-	Location *url.URL
77
-
78
-	// A Websocket client origin.
79
-	Origin *url.URL
80
-
81
-	// WebSocket subprotocols.
82
-	Protocol []string
83
-
84
-	// WebSocket protocol version.
85
-	Version int
86
-
87
-	// TLS config for secure WebSocket (wss).
88
-	TlsConfig *tls.Config
89
-
90
-	// Additional header fields to be sent in WebSocket opening handshake.
91
-	Header http.Header
92
-
93
-	handshakeData map[string]string
94
-}
95
-
96
-// serverHandshaker is an interface to handle WebSocket server side handshake.
97
-type serverHandshaker interface {
98
-	// ReadHandshake reads handshake request message from client.
99
-	// Returns http response code and error if any.
100
-	ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
101
-
102
-	// AcceptHandshake accepts the client handshake request and sends
103
-	// handshake response back to client.
104
-	AcceptHandshake(buf *bufio.Writer) (err error)
105
-
106
-	// NewServerConn creates a new WebSocket connection.
107
-	NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
108
-}
109
-
110
-// frameReader is an interface to read a WebSocket frame.
111
-type frameReader interface {
112
-	// Reader is to read payload of the frame.
113
-	io.Reader
114
-
115
-	// PayloadType returns payload type.
116
-	PayloadType() byte
117
-
118
-	// HeaderReader returns a reader to read header of the frame.
119
-	HeaderReader() io.Reader
120
-
121
-	// TrailerReader returns a reader to read trailer of the frame.
122
-	// If it returns nil, there is no trailer in the frame.
123
-	TrailerReader() io.Reader
124
-
125
-	// Len returns total length of the frame, including header and trailer.
126
-	Len() int
127
-}
128
-
129
-// frameReaderFactory is an interface to creates new frame reader.
130
-type frameReaderFactory interface {
131
-	NewFrameReader() (r frameReader, err error)
132
-}
133
-
134
-// frameWriter is an interface to write a WebSocket frame.
135
-type frameWriter interface {
136
-	// Writer is to write playload of the frame.
137
-	io.WriteCloser
138
-}
139
-
140
-// frameWriterFactory is an interface to create new frame writer.
141
-type frameWriterFactory interface {
142
-	NewFrameWriter(payloadType byte) (w frameWriter, err error)
143
-}
144
-
145
-type frameHandler interface {
146
-	HandleFrame(frame frameReader) (r frameReader, err error)
147
-	WriteClose(status int) (err error)
148
-}
149
-
150
-// Conn represents a WebSocket connection.
151
-type Conn struct {
152
-	config  *Config
153
-	request *http.Request
154
-
155
-	buf *bufio.ReadWriter
156
-	rwc io.ReadWriteCloser
157
-
158
-	rio sync.Mutex
159
-	frameReaderFactory
160
-	frameReader
161
-
162
-	wio sync.Mutex
163
-	frameWriterFactory
164
-
165
-	frameHandler
166
-	PayloadType        byte
167
-	defaultCloseStatus int
168
-}
169
-
170
-// Read implements the io.Reader interface:
171
-// it reads data of a frame from the WebSocket connection.
172
-// if msg is not large enough for the frame data, it fills the msg and next Read
173
-// will read the rest of the frame data.
174
-// it reads Text frame or Binary frame.
175
-func (ws *Conn) Read(msg []byte) (n int, err error) {
176
-	ws.rio.Lock()
177
-	defer ws.rio.Unlock()
178
-again:
179
-	if ws.frameReader == nil {
180
-		frame, err := ws.frameReaderFactory.NewFrameReader()
181
-		if err != nil {
182
-			return 0, err
183
-		}
184
-		ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
185
-		if err != nil {
186
-			return 0, err
187
-		}
188
-		if ws.frameReader == nil {
189
-			goto again
190
-		}
191
-	}
192
-	n, err = ws.frameReader.Read(msg)
193
-	if err == io.EOF {
194
-		if trailer := ws.frameReader.TrailerReader(); trailer != nil {
195
-			io.Copy(ioutil.Discard, trailer)
196
-		}
197
-		ws.frameReader = nil
198
-		goto again
199
-	}
200
-	return n, err
201
-}
202
-
203
-// Write implements the io.Writer interface:
204
-// it writes data as a frame to the WebSocket connection.
205
-func (ws *Conn) Write(msg []byte) (n int, err error) {
206
-	ws.wio.Lock()
207
-	defer ws.wio.Unlock()
208
-	w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
209
-	if err != nil {
210
-		return 0, err
211
-	}
212
-	n, err = w.Write(msg)
213
-	w.Close()
214
-	if err != nil {
215
-		return n, err
216
-	}
217
-	return n, err
218
-}
219
-
220
-// Close implements the io.Closer interface.
221
-func (ws *Conn) Close() error {
222
-	err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
223
-	if err != nil {
224
-		return err
225
-	}
226
-	return ws.rwc.Close()
227
-}
228
-
229
-func (ws *Conn) IsClientConn() bool { return ws.request == nil }
230
-func (ws *Conn) IsServerConn() bool { return ws.request != nil }
231
-
232
-// LocalAddr returns the WebSocket Origin for the connection for client, or
233
-// the WebSocket location for server.
234
-func (ws *Conn) LocalAddr() net.Addr {
235
-	if ws.IsClientConn() {
236
-		return &Addr{ws.config.Origin}
237
-	}
238
-	return &Addr{ws.config.Location}
239
-}
240
-
241
-// RemoteAddr returns the WebSocket location for the connection for client, or
242
-// the Websocket Origin for server.
243
-func (ws *Conn) RemoteAddr() net.Addr {
244
-	if ws.IsClientConn() {
245
-		return &Addr{ws.config.Location}
246
-	}
247
-	return &Addr{ws.config.Origin}
248
-}
249
-
250
-var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
251
-
252
-// SetDeadline sets the connection's network read & write deadlines.
253
-func (ws *Conn) SetDeadline(t time.Time) error {
254
-	if conn, ok := ws.rwc.(net.Conn); ok {
255
-		return conn.SetDeadline(t)
256
-	}
257
-	return errSetDeadline
258
-}
259
-
260
-// SetReadDeadline sets the connection's network read deadline.
261
-func (ws *Conn) SetReadDeadline(t time.Time) error {
262
-	if conn, ok := ws.rwc.(net.Conn); ok {
263
-		return conn.SetReadDeadline(t)
264
-	}
265
-	return errSetDeadline
266
-}
267
-
268
-// SetWriteDeadline sets the connection's network write deadline.
269
-func (ws *Conn) SetWriteDeadline(t time.Time) error {
270
-	if conn, ok := ws.rwc.(net.Conn); ok {
271
-		return conn.SetWriteDeadline(t)
272
-	}
273
-	return errSetDeadline
274
-}
275
-
276
-// Config returns the WebSocket config.
277
-func (ws *Conn) Config() *Config { return ws.config }
278
-
279
-// Request returns the http request upgraded to the WebSocket.
280
-// It is nil for client side.
281
-func (ws *Conn) Request() *http.Request { return ws.request }
282
-
283
-// Codec represents a symmetric pair of functions that implement a codec.
284
-type Codec struct {
285
-	Marshal   func(v interface{}) (data []byte, payloadType byte, err error)
286
-	Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
287
-}
288
-
289
-// Send sends v marshaled by cd.Marshal as single frame to ws.
290
-func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
291
-	data, payloadType, err := cd.Marshal(v)
292
-	if err != nil {
293
-		return err
294
-	}
295
-	ws.wio.Lock()
296
-	defer ws.wio.Unlock()
297
-	w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
298
-	if err != nil {
299
-		return err
300
-	}
301
-	_, err = w.Write(data)
302
-	w.Close()
303
-	return err
304
-}
305
-
306
-// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
307
-func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
308
-	ws.rio.Lock()
309
-	defer ws.rio.Unlock()
310
-	if ws.frameReader != nil {
311
-		_, err = io.Copy(ioutil.Discard, ws.frameReader)
312
-		if err != nil {
313
-			return err
314
-		}
315
-		ws.frameReader = nil
316
-	}
317
-again:
318
-	frame, err := ws.frameReaderFactory.NewFrameReader()
319
-	if err != nil {
320
-		return err
321
-	}
322
-	frame, err = ws.frameHandler.HandleFrame(frame)
323
-	if err != nil {
324
-		return err
325
-	}
326
-	if frame == nil {
327
-		goto again
328
-	}
329
-	payloadType := frame.PayloadType()
330
-	data, err := ioutil.ReadAll(frame)
331
-	if err != nil {
332
-		return err
333
-	}
334
-	return cd.Unmarshal(data, payloadType, v)
335
-}
336
-
337
-func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
338
-	switch data := v.(type) {
339
-	case string:
340
-		return []byte(data), TextFrame, nil
341
-	case []byte:
342
-		return data, BinaryFrame, nil
343
-	}
344
-	return nil, UnknownFrame, ErrNotSupported
345
-}
346
-
347
-func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
348
-	switch data := v.(type) {
349
-	case *string:
350
-		*data = string(msg)
351
-		return nil
352
-	case *[]byte:
353
-		*data = msg
354
-		return nil
355
-	}
356
-	return ErrNotSupported
357
-}
358
-
359
-/*
360
-Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
361
-To send/receive text frame, use string type.
362
-To send/receive binary frame, use []byte type.
363
-
364
-Trivial usage:
365
-
366
-	import "websocket"
367
-
368
-	// receive text frame
369
-	var message string
370
-	websocket.Message.Receive(ws, &message)
371
-
372
-	// send text frame
373
-	message = "hello"
374
-	websocket.Message.Send(ws, message)
375
-
376
-	// receive binary frame
377
-	var data []byte
378
-	websocket.Message.Receive(ws, &data)
379
-
380
-	// send binary frame
381
-	data = []byte{0, 1, 2}
382
-	websocket.Message.Send(ws, data)
383
-
384
-*/
385
-var Message = Codec{marshal, unmarshal}
386
-
387
-func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
388
-	msg, err = json.Marshal(v)
389
-	return msg, TextFrame, err
390
-}
391
-
392
-func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
393
-	return json.Unmarshal(msg, v)
394
-}
395
-
396
-/*
397
-JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
398
-
399
-Trivial usage:
400
-
401
-	import "websocket"
402
-
403
-	type T struct {
404
-		Msg string
405
-		Count int
406
-	}
407
-
408
-	// receive JSON type T
409
-	var data T
410
-	websocket.JSON.Receive(ws, &data)
411
-
412
-	// send JSON type T
413
-	websocket.JSON.Send(ws, data)
414
-*/
415
-var JSON = Codec{jsonMarshal, jsonUnmarshal}
416 1
new file mode 100644
... ...
@@ -0,0 +1,113 @@
0
+// Copyright 2009 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package websocket
5
+
6
+import (
7
+	"bufio"
8
+	"crypto/tls"
9
+	"io"
10
+	"net"
11
+	"net/http"
12
+	"net/url"
13
+)
14
+
15
+// DialError is an error that occurs while dialling a websocket server.
16
+type DialError struct {
17
+	*Config
18
+	Err error
19
+}
20
+
21
+func (e *DialError) Error() string {
22
+	return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
23
+}
24
+
25
+// NewConfig creates a new WebSocket config for client connection.
26
+func NewConfig(server, origin string) (config *Config, err error) {
27
+	config = new(Config)
28
+	config.Version = ProtocolVersionHybi13
29
+	config.Location, err = url.ParseRequestURI(server)
30
+	if err != nil {
31
+		return
32
+	}
33
+	config.Origin, err = url.ParseRequestURI(origin)
34
+	if err != nil {
35
+		return
36
+	}
37
+	config.Header = http.Header(make(map[string][]string))
38
+	return
39
+}
40
+
41
+// NewClient creates a new WebSocket client connection over rwc.
42
+func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
43
+	br := bufio.NewReader(rwc)
44
+	bw := bufio.NewWriter(rwc)
45
+	err = hybiClientHandshake(config, br, bw)
46
+	if err != nil {
47
+		return
48
+	}
49
+	buf := bufio.NewReadWriter(br, bw)
50
+	ws = newHybiClientConn(config, buf, rwc)
51
+	return
52
+}
53
+
54
+// Dial opens a new client connection to a WebSocket.
55
+func Dial(url_, protocol, origin string) (ws *Conn, err error) {
56
+	config, err := NewConfig(url_, origin)
57
+	if err != nil {
58
+		return nil, err
59
+	}
60
+	if protocol != "" {
61
+		config.Protocol = []string{protocol}
62
+	}
63
+	return DialConfig(config)
64
+}
65
+
66
+var portMap = map[string]string{
67
+	"ws":  "80",
68
+	"wss": "443",
69
+}
70
+
71
+func parseAuthority(location *url.URL) string {
72
+	if _, ok := portMap[location.Scheme]; ok {
73
+		if _, _, err := net.SplitHostPort(location.Host); err != nil {
74
+			return net.JoinHostPort(location.Host, portMap[location.Scheme])
75
+		}
76
+	}
77
+	return location.Host
78
+}
79
+
80
+// DialConfig opens a new client connection to a WebSocket with a config.
81
+func DialConfig(config *Config) (ws *Conn, err error) {
82
+	var client net.Conn
83
+	if config.Location == nil {
84
+		return nil, &DialError{config, ErrBadWebSocketLocation}
85
+	}
86
+	if config.Origin == nil {
87
+		return nil, &DialError{config, ErrBadWebSocketOrigin}
88
+	}
89
+	switch config.Location.Scheme {
90
+	case "ws":
91
+		client, err = net.Dial("tcp", parseAuthority(config.Location))
92
+
93
+	case "wss":
94
+		client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
95
+
96
+	default:
97
+		err = ErrBadScheme
98
+	}
99
+	if err != nil {
100
+		goto Error
101
+	}
102
+
103
+	ws, err = NewClient(config, client)
104
+	if err != nil {
105
+		client.Close()
106
+		goto Error
107
+	}
108
+	return
109
+
110
+Error:
111
+	return nil, &DialError{config, err}
112
+}
0 113
new file mode 100644
... ...
@@ -0,0 +1,564 @@
0
+// Copyright 2011 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package websocket
5
+
6
+// This file implements a protocol of hybi draft.
7
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
8
+
9
+import (
10
+	"bufio"
11
+	"bytes"
12
+	"crypto/rand"
13
+	"crypto/sha1"
14
+	"encoding/base64"
15
+	"encoding/binary"
16
+	"fmt"
17
+	"io"
18
+	"io/ioutil"
19
+	"net/http"
20
+	"net/url"
21
+	"strings"
22
+)
23
+
24
+const (
25
+	websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
26
+
27
+	closeStatusNormal            = 1000
28
+	closeStatusGoingAway         = 1001
29
+	closeStatusProtocolError     = 1002
30
+	closeStatusUnsupportedData   = 1003
31
+	closeStatusFrameTooLarge     = 1004
32
+	closeStatusNoStatusRcvd      = 1005
33
+	closeStatusAbnormalClosure   = 1006
34
+	closeStatusBadMessageData    = 1007
35
+	closeStatusPolicyViolation   = 1008
36
+	closeStatusTooBigData        = 1009
37
+	closeStatusExtensionMismatch = 1010
38
+
39
+	maxControlFramePayloadLength = 125
40
+)
41
+
42
+var (
43
+	ErrBadMaskingKey         = &ProtocolError{"bad masking key"}
44
+	ErrBadPongMessage        = &ProtocolError{"bad pong message"}
45
+	ErrBadClosingStatus      = &ProtocolError{"bad closing status"}
46
+	ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
47
+	ErrNotImplemented        = &ProtocolError{"not implemented"}
48
+
49
+	handshakeHeader = map[string]bool{
50
+		"Host":                   true,
51
+		"Upgrade":                true,
52
+		"Connection":             true,
53
+		"Sec-Websocket-Key":      true,
54
+		"Sec-Websocket-Origin":   true,
55
+		"Sec-Websocket-Version":  true,
56
+		"Sec-Websocket-Protocol": true,
57
+		"Sec-Websocket-Accept":   true,
58
+	}
59
+)
60
+
61
+// A hybiFrameHeader is a frame header as defined in hybi draft.
62
+type hybiFrameHeader struct {
63
+	Fin        bool
64
+	Rsv        [3]bool
65
+	OpCode     byte
66
+	Length     int64
67
+	MaskingKey []byte
68
+
69
+	data *bytes.Buffer
70
+}
71
+
72
+// A hybiFrameReader is a reader for hybi frame.
73
+type hybiFrameReader struct {
74
+	reader io.Reader
75
+
76
+	header hybiFrameHeader
77
+	pos    int64
78
+	length int
79
+}
80
+
81
+func (frame *hybiFrameReader) Read(msg []byte) (n int, err error) {
82
+	n, err = frame.reader.Read(msg)
83
+	if err != nil {
84
+		return 0, err
85
+	}
86
+	if frame.header.MaskingKey != nil {
87
+		for i := 0; i < n; i++ {
88
+			msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
89
+			frame.pos++
90
+		}
91
+	}
92
+	return n, err
93
+}
94
+
95
+func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
96
+
97
+func (frame *hybiFrameReader) HeaderReader() io.Reader {
98
+	if frame.header.data == nil {
99
+		return nil
100
+	}
101
+	if frame.header.data.Len() == 0 {
102
+		return nil
103
+	}
104
+	return frame.header.data
105
+}
106
+
107
+func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
108
+
109
+func (frame *hybiFrameReader) Len() (n int) { return frame.length }
110
+
111
+// A hybiFrameReaderFactory creates new frame reader based on its frame type.
112
+type hybiFrameReaderFactory struct {
113
+	*bufio.Reader
114
+}
115
+
116
+// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
117
+// See Section 5.2 Base Framing protocol for detail.
118
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
119
+func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err error) {
120
+	hybiFrame := new(hybiFrameReader)
121
+	frame = hybiFrame
122
+	var header []byte
123
+	var b byte
124
+	// First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
125
+	b, err = buf.ReadByte()
126
+	if err != nil {
127
+		return
128
+	}
129
+	header = append(header, b)
130
+	hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
131
+	for i := 0; i < 3; i++ {
132
+		j := uint(6 - i)
133
+		hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
134
+	}
135
+	hybiFrame.header.OpCode = header[0] & 0x0f
136
+
137
+	// Second byte. Mask/Payload len(7bits)
138
+	b, err = buf.ReadByte()
139
+	if err != nil {
140
+		return
141
+	}
142
+	header = append(header, b)
143
+	mask := (b & 0x80) != 0
144
+	b &= 0x7f
145
+	lengthFields := 0
146
+	switch {
147
+	case b <= 125: // Payload length 7bits.
148
+		hybiFrame.header.Length = int64(b)
149
+	case b == 126: // Payload length 7+16bits
150
+		lengthFields = 2
151
+	case b == 127: // Payload length 7+64bits
152
+		lengthFields = 8
153
+	}
154
+	for i := 0; i < lengthFields; i++ {
155
+		b, err = buf.ReadByte()
156
+		if err != nil {
157
+			return
158
+		}
159
+		header = append(header, b)
160
+		hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
161
+	}
162
+	if mask {
163
+		// Masking key. 4 bytes.
164
+		for i := 0; i < 4; i++ {
165
+			b, err = buf.ReadByte()
166
+			if err != nil {
167
+				return
168
+			}
169
+			header = append(header, b)
170
+			hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
171
+		}
172
+	}
173
+	hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
174
+	hybiFrame.header.data = bytes.NewBuffer(header)
175
+	hybiFrame.length = len(header) + int(hybiFrame.header.Length)
176
+	return
177
+}
178
+
179
+// A HybiFrameWriter is a writer for hybi frame.
180
+type hybiFrameWriter struct {
181
+	writer *bufio.Writer
182
+
183
+	header *hybiFrameHeader
184
+}
185
+
186
+func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
187
+	var header []byte
188
+	var b byte
189
+	if frame.header.Fin {
190
+		b |= 0x80
191
+	}
192
+	for i := 0; i < 3; i++ {
193
+		if frame.header.Rsv[i] {
194
+			j := uint(6 - i)
195
+			b |= 1 << j
196
+		}
197
+	}
198
+	b |= frame.header.OpCode
199
+	header = append(header, b)
200
+	if frame.header.MaskingKey != nil {
201
+		b = 0x80
202
+	} else {
203
+		b = 0
204
+	}
205
+	lengthFields := 0
206
+	length := len(msg)
207
+	switch {
208
+	case length <= 125:
209
+		b |= byte(length)
210
+	case length < 65536:
211
+		b |= 126
212
+		lengthFields = 2
213
+	default:
214
+		b |= 127
215
+		lengthFields = 8
216
+	}
217
+	header = append(header, b)
218
+	for i := 0; i < lengthFields; i++ {
219
+		j := uint((lengthFields - i - 1) * 8)
220
+		b = byte((length >> j) & 0xff)
221
+		header = append(header, b)
222
+	}
223
+	if frame.header.MaskingKey != nil {
224
+		if len(frame.header.MaskingKey) != 4 {
225
+			return 0, ErrBadMaskingKey
226
+		}
227
+		header = append(header, frame.header.MaskingKey...)
228
+		frame.writer.Write(header)
229
+		data := make([]byte, length)
230
+		for i := range data {
231
+			data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
232
+		}
233
+		frame.writer.Write(data)
234
+		err = frame.writer.Flush()
235
+		return length, err
236
+	}
237
+	frame.writer.Write(header)
238
+	frame.writer.Write(msg)
239
+	err = frame.writer.Flush()
240
+	return length, err
241
+}
242
+
243
+func (frame *hybiFrameWriter) Close() error { return nil }
244
+
245
+type hybiFrameWriterFactory struct {
246
+	*bufio.Writer
247
+	needMaskingKey bool
248
+}
249
+
250
+func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
251
+	frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
252
+	if buf.needMaskingKey {
253
+		frameHeader.MaskingKey, err = generateMaskingKey()
254
+		if err != nil {
255
+			return nil, err
256
+		}
257
+	}
258
+	return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
259
+}
260
+
261
+type hybiFrameHandler struct {
262
+	conn        *Conn
263
+	payloadType byte
264
+}
265
+
266
+func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) {
267
+	if handler.conn.IsServerConn() {
268
+		// The client MUST mask all frames sent to the server.
269
+		if frame.(*hybiFrameReader).header.MaskingKey == nil {
270
+			handler.WriteClose(closeStatusProtocolError)
271
+			return nil, io.EOF
272
+		}
273
+	} else {
274
+		// The server MUST NOT mask all frames.
275
+		if frame.(*hybiFrameReader).header.MaskingKey != nil {
276
+			handler.WriteClose(closeStatusProtocolError)
277
+			return nil, io.EOF
278
+		}
279
+	}
280
+	if header := frame.HeaderReader(); header != nil {
281
+		io.Copy(ioutil.Discard, header)
282
+	}
283
+	switch frame.PayloadType() {
284
+	case ContinuationFrame:
285
+		frame.(*hybiFrameReader).header.OpCode = handler.payloadType
286
+	case TextFrame, BinaryFrame:
287
+		handler.payloadType = frame.PayloadType()
288
+	case CloseFrame:
289
+		return nil, io.EOF
290
+	case PingFrame:
291
+		pingMsg := make([]byte, maxControlFramePayloadLength)
292
+		n, err := io.ReadFull(frame, pingMsg)
293
+		if err != nil && err != io.ErrUnexpectedEOF {
294
+			return nil, err
295
+		}
296
+		io.Copy(ioutil.Discard, frame)
297
+		n, err = handler.WritePong(pingMsg[:n])
298
+		if err != nil {
299
+			return nil, err
300
+		}
301
+		return nil, nil
302
+	case PongFrame:
303
+		return nil, ErrNotImplemented
304
+	}
305
+	return frame, nil
306
+}
307
+
308
+func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
309
+	handler.conn.wio.Lock()
310
+	defer handler.conn.wio.Unlock()
311
+	w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
312
+	if err != nil {
313
+		return err
314
+	}
315
+	msg := make([]byte, 2)
316
+	binary.BigEndian.PutUint16(msg, uint16(status))
317
+	_, err = w.Write(msg)
318
+	w.Close()
319
+	return err
320
+}
321
+
322
+func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
323
+	handler.conn.wio.Lock()
324
+	defer handler.conn.wio.Unlock()
325
+	w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
326
+	if err != nil {
327
+		return 0, err
328
+	}
329
+	n, err = w.Write(msg)
330
+	w.Close()
331
+	return n, err
332
+}
333
+
334
+// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
335
+func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
336
+	if buf == nil {
337
+		br := bufio.NewReader(rwc)
338
+		bw := bufio.NewWriter(rwc)
339
+		buf = bufio.NewReadWriter(br, bw)
340
+	}
341
+	ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
342
+		frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
343
+		frameWriterFactory: hybiFrameWriterFactory{
344
+			buf.Writer, request == nil},
345
+		PayloadType:        TextFrame,
346
+		defaultCloseStatus: closeStatusNormal}
347
+	ws.frameHandler = &hybiFrameHandler{conn: ws}
348
+	return ws
349
+}
350
+
351
+// generateMaskingKey generates a masking key for a frame.
352
+func generateMaskingKey() (maskingKey []byte, err error) {
353
+	maskingKey = make([]byte, 4)
354
+	if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
355
+		return
356
+	}
357
+	return
358
+}
359
+
360
+// generateNonce generates a nonce consisting of a randomly selected 16-byte
361
+// value that has been base64-encoded.
362
+func generateNonce() (nonce []byte) {
363
+	key := make([]byte, 16)
364
+	if _, err := io.ReadFull(rand.Reader, key); err != nil {
365
+		panic(err)
366
+	}
367
+	nonce = make([]byte, 24)
368
+	base64.StdEncoding.Encode(nonce, key)
369
+	return
370
+}
371
+
372
+// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
373
+// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
374
+func getNonceAccept(nonce []byte) (expected []byte, err error) {
375
+	h := sha1.New()
376
+	if _, err = h.Write(nonce); err != nil {
377
+		return
378
+	}
379
+	if _, err = h.Write([]byte(websocketGUID)); err != nil {
380
+		return
381
+	}
382
+	expected = make([]byte, 28)
383
+	base64.StdEncoding.Encode(expected, h.Sum(nil))
384
+	return
385
+}
386
+
387
+// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
388
+func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
389
+	bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
390
+
391
+	bw.WriteString("Host: " + config.Location.Host + "\r\n")
392
+	bw.WriteString("Upgrade: websocket\r\n")
393
+	bw.WriteString("Connection: Upgrade\r\n")
394
+	nonce := generateNonce()
395
+	if config.handshakeData != nil {
396
+		nonce = []byte(config.handshakeData["key"])
397
+	}
398
+	bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
399
+	bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
400
+
401
+	if config.Version != ProtocolVersionHybi13 {
402
+		return ErrBadProtocolVersion
403
+	}
404
+
405
+	bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
406
+	if len(config.Protocol) > 0 {
407
+		bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
408
+	}
409
+	// TODO(ukai): send Sec-WebSocket-Extensions.
410
+	err = config.Header.WriteSubset(bw, handshakeHeader)
411
+	if err != nil {
412
+		return err
413
+	}
414
+
415
+	bw.WriteString("\r\n")
416
+	if err = bw.Flush(); err != nil {
417
+		return err
418
+	}
419
+
420
+	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
421
+	if err != nil {
422
+		return err
423
+	}
424
+	if resp.StatusCode != 101 {
425
+		return ErrBadStatus
426
+	}
427
+	if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
428
+		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
429
+		return ErrBadUpgrade
430
+	}
431
+	expectedAccept, err := getNonceAccept(nonce)
432
+	if err != nil {
433
+		return err
434
+	}
435
+	if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
436
+		return ErrChallengeResponse
437
+	}
438
+	if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
439
+		return ErrUnsupportedExtensions
440
+	}
441
+	offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
442
+	if offeredProtocol != "" {
443
+		protocolMatched := false
444
+		for i := 0; i < len(config.Protocol); i++ {
445
+			if config.Protocol[i] == offeredProtocol {
446
+				protocolMatched = true
447
+				break
448
+			}
449
+		}
450
+		if !protocolMatched {
451
+			return ErrBadWebSocketProtocol
452
+		}
453
+		config.Protocol = []string{offeredProtocol}
454
+	}
455
+
456
+	return nil
457
+}
458
+
459
+// newHybiClientConn creates a client WebSocket connection after handshake.
460
+func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
461
+	return newHybiConn(config, buf, rwc, nil)
462
+}
463
+
464
+// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
465
+type hybiServerHandshaker struct {
466
+	*Config
467
+	accept []byte
468
+}
469
+
470
+func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
471
+	c.Version = ProtocolVersionHybi13
472
+	if req.Method != "GET" {
473
+		return http.StatusMethodNotAllowed, ErrBadRequestMethod
474
+	}
475
+	// HTTP version can be safely ignored.
476
+
477
+	if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
478
+		!strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
479
+		return http.StatusBadRequest, ErrNotWebSocket
480
+	}
481
+
482
+	key := req.Header.Get("Sec-Websocket-Key")
483
+	if key == "" {
484
+		return http.StatusBadRequest, ErrChallengeResponse
485
+	}
486
+	version := req.Header.Get("Sec-Websocket-Version")
487
+	switch version {
488
+	case "13":
489
+		c.Version = ProtocolVersionHybi13
490
+	default:
491
+		return http.StatusBadRequest, ErrBadWebSocketVersion
492
+	}
493
+	var scheme string
494
+	if req.TLS != nil {
495
+		scheme = "wss"
496
+	} else {
497
+		scheme = "ws"
498
+	}
499
+	c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
500
+	if err != nil {
501
+		return http.StatusBadRequest, err
502
+	}
503
+	protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
504
+	if protocol != "" {
505
+		protocols := strings.Split(protocol, ",")
506
+		for i := 0; i < len(protocols); i++ {
507
+			c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
508
+		}
509
+	}
510
+	c.accept, err = getNonceAccept([]byte(key))
511
+	if err != nil {
512
+		return http.StatusInternalServerError, err
513
+	}
514
+	return http.StatusSwitchingProtocols, nil
515
+}
516
+
517
+// Origin parses Origin header in "req".
518
+// If origin is "null", returns (nil, nil).
519
+func Origin(config *Config, req *http.Request) (*url.URL, error) {
520
+	var origin string
521
+	switch config.Version {
522
+	case ProtocolVersionHybi13:
523
+		origin = req.Header.Get("Origin")
524
+	}
525
+	if origin == "null" {
526
+		return nil, nil
527
+	}
528
+	return url.ParseRequestURI(origin)
529
+}
530
+
531
+func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
532
+	if len(c.Protocol) > 0 {
533
+		if len(c.Protocol) != 1 {
534
+			// You need choose a Protocol in Handshake func in Server.
535
+			return ErrBadWebSocketProtocol
536
+		}
537
+	}
538
+	buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
539
+	buf.WriteString("Upgrade: websocket\r\n")
540
+	buf.WriteString("Connection: Upgrade\r\n")
541
+	buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
542
+	if len(c.Protocol) > 0 {
543
+		buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
544
+	}
545
+	// TODO(ukai): send Sec-WebSocket-Extensions.
546
+	if c.Header != nil {
547
+		err := c.Header.WriteSubset(buf, handshakeHeader)
548
+		if err != nil {
549
+			return err
550
+		}
551
+	}
552
+	buf.WriteString("\r\n")
553
+	return buf.Flush()
554
+}
555
+
556
+func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
557
+	return newHybiServerConn(c.Config, buf, rwc, request)
558
+}
559
+
560
+// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
561
+func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
562
+	return newHybiConn(config, buf, rwc, request)
563
+}
0 564
new file mode 100644
... ...
@@ -0,0 +1,114 @@
0
+// Copyright 2009 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package websocket
5
+
6
+import (
7
+	"bufio"
8
+	"fmt"
9
+	"io"
10
+	"net/http"
11
+)
12
+
13
+func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
14
+	var hs serverHandshaker = &hybiServerHandshaker{Config: config}
15
+	code, err := hs.ReadHandshake(buf.Reader, req)
16
+	if err == ErrBadWebSocketVersion {
17
+		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
18
+		fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
19
+		buf.WriteString("\r\n")
20
+		buf.WriteString(err.Error())
21
+		buf.Flush()
22
+		return
23
+	}
24
+	if err != nil {
25
+		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
26
+		buf.WriteString("\r\n")
27
+		buf.WriteString(err.Error())
28
+		buf.Flush()
29
+		return
30
+	}
31
+	if handshake != nil {
32
+		err = handshake(config, req)
33
+		if err != nil {
34
+			code = http.StatusForbidden
35
+			fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
36
+			buf.WriteString("\r\n")
37
+			buf.Flush()
38
+			return
39
+		}
40
+	}
41
+	err = hs.AcceptHandshake(buf.Writer)
42
+	if err != nil {
43
+		code = http.StatusBadRequest
44
+		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
45
+		buf.WriteString("\r\n")
46
+		buf.Flush()
47
+		return
48
+	}
49
+	conn = hs.NewServerConn(buf, rwc, req)
50
+	return
51
+}
52
+
53
+// Server represents a server of a WebSocket.
54
+type Server struct {
55
+	// Config is a WebSocket configuration for new WebSocket connection.
56
+	Config
57
+
58
+	// Handshake is an optional function in WebSocket handshake.
59
+	// For example, you can check, or don't check Origin header.
60
+	// Another example, you can select config.Protocol.
61
+	Handshake func(*Config, *http.Request) error
62
+
63
+	// Handler handles a WebSocket connection.
64
+	Handler
65
+}
66
+
67
+// ServeHTTP implements the http.Handler interface for a WebSocket
68
+func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
69
+	s.serveWebSocket(w, req)
70
+}
71
+
72
+func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
73
+	rwc, buf, err := w.(http.Hijacker).Hijack()
74
+	if err != nil {
75
+		panic("Hijack failed: " + err.Error())
76
+		return
77
+	}
78
+	// The server should abort the WebSocket connection if it finds
79
+	// the client did not send a handshake that matches with protocol
80
+	// specification.
81
+	defer rwc.Close()
82
+	conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
83
+	if err != nil {
84
+		return
85
+	}
86
+	if conn == nil {
87
+		panic("unexpected nil conn")
88
+	}
89
+	s.Handler(conn)
90
+}
91
+
92
+// Handler is a simple interface to a WebSocket browser client.
93
+// It checks if Origin header is valid URL by default.
94
+// You might want to verify websocket.Conn.Config().Origin in the func.
95
+// If you use Server instead of Handler, you could call websocket.Origin and
96
+// check the origin in your Handshake func. So, if you want to accept
97
+// non-browser clients, which do not send an Origin header, set a
98
+// Server.Handshake that does not check the origin.
99
+type Handler func(*Conn)
100
+
101
+func checkOrigin(config *Config, req *http.Request) (err error) {
102
+	config.Origin, err = Origin(config, req)
103
+	if err == nil && config.Origin == nil {
104
+		return fmt.Errorf("null origin")
105
+	}
106
+	return err
107
+}
108
+
109
+// ServeHTTP implements the http.Handler interface for a WebSocket
110
+func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
111
+	s := Server{Handler: h, Handshake: checkOrigin}
112
+	s.serveWebSocket(w, req)
113
+}
0 114
new file mode 100644
... ...
@@ -0,0 +1,412 @@
0
+// Copyright 2009 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+// Package websocket implements a client and server for the WebSocket protocol
5
+// as specified in RFC 6455.
6
+package websocket // import "golang.org/x/net/websocket"
7
+
8
+import (
9
+	"bufio"
10
+	"crypto/tls"
11
+	"encoding/json"
12
+	"errors"
13
+	"io"
14
+	"io/ioutil"
15
+	"net"
16
+	"net/http"
17
+	"net/url"
18
+	"sync"
19
+	"time"
20
+)
21
+
22
+const (
23
+	ProtocolVersionHybi13    = 13
24
+	ProtocolVersionHybi      = ProtocolVersionHybi13
25
+	SupportedProtocolVersion = "13"
26
+
27
+	ContinuationFrame = 0
28
+	TextFrame         = 1
29
+	BinaryFrame       = 2
30
+	CloseFrame        = 8
31
+	PingFrame         = 9
32
+	PongFrame         = 10
33
+	UnknownFrame      = 255
34
+)
35
+
36
+// ProtocolError represents WebSocket protocol errors.
37
+type ProtocolError struct {
38
+	ErrorString string
39
+}
40
+
41
+func (err *ProtocolError) Error() string { return err.ErrorString }
42
+
43
+var (
44
+	ErrBadProtocolVersion   = &ProtocolError{"bad protocol version"}
45
+	ErrBadScheme            = &ProtocolError{"bad scheme"}
46
+	ErrBadStatus            = &ProtocolError{"bad status"}
47
+	ErrBadUpgrade           = &ProtocolError{"missing or bad upgrade"}
48
+	ErrBadWebSocketOrigin   = &ProtocolError{"missing or bad WebSocket-Origin"}
49
+	ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
50
+	ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
51
+	ErrBadWebSocketVersion  = &ProtocolError{"missing or bad WebSocket Version"}
52
+	ErrChallengeResponse    = &ProtocolError{"mismatch challenge/response"}
53
+	ErrBadFrame             = &ProtocolError{"bad frame"}
54
+	ErrBadFrameBoundary     = &ProtocolError{"not on frame boundary"}
55
+	ErrNotWebSocket         = &ProtocolError{"not websocket protocol"}
56
+	ErrBadRequestMethod     = &ProtocolError{"bad method"}
57
+	ErrNotSupported         = &ProtocolError{"not supported"}
58
+)
59
+
60
+// Addr is an implementation of net.Addr for WebSocket.
61
+type Addr struct {
62
+	*url.URL
63
+}
64
+
65
+// Network returns the network type for a WebSocket, "websocket".
66
+func (addr *Addr) Network() string { return "websocket" }
67
+
68
+// Config is a WebSocket configuration
69
+type Config struct {
70
+	// A WebSocket server address.
71
+	Location *url.URL
72
+
73
+	// A Websocket client origin.
74
+	Origin *url.URL
75
+
76
+	// WebSocket subprotocols.
77
+	Protocol []string
78
+
79
+	// WebSocket protocol version.
80
+	Version int
81
+
82
+	// TLS config for secure WebSocket (wss).
83
+	TlsConfig *tls.Config
84
+
85
+	// Additional header fields to be sent in WebSocket opening handshake.
86
+	Header http.Header
87
+
88
+	handshakeData map[string]string
89
+}
90
+
91
+// serverHandshaker is an interface to handle WebSocket server side handshake.
92
+type serverHandshaker interface {
93
+	// ReadHandshake reads handshake request message from client.
94
+	// Returns http response code and error if any.
95
+	ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
96
+
97
+	// AcceptHandshake accepts the client handshake request and sends
98
+	// handshake response back to client.
99
+	AcceptHandshake(buf *bufio.Writer) (err error)
100
+
101
+	// NewServerConn creates a new WebSocket connection.
102
+	NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
103
+}
104
+
105
+// frameReader is an interface to read a WebSocket frame.
106
+type frameReader interface {
107
+	// Reader is to read payload of the frame.
108
+	io.Reader
109
+
110
+	// PayloadType returns payload type.
111
+	PayloadType() byte
112
+
113
+	// HeaderReader returns a reader to read header of the frame.
114
+	HeaderReader() io.Reader
115
+
116
+	// TrailerReader returns a reader to read trailer of the frame.
117
+	// If it returns nil, there is no trailer in the frame.
118
+	TrailerReader() io.Reader
119
+
120
+	// Len returns total length of the frame, including header and trailer.
121
+	Len() int
122
+}
123
+
124
+// frameReaderFactory is an interface to creates new frame reader.
125
+type frameReaderFactory interface {
126
+	NewFrameReader() (r frameReader, err error)
127
+}
128
+
129
+// frameWriter is an interface to write a WebSocket frame.
130
+type frameWriter interface {
131
+	// Writer is to write payload of the frame.
132
+	io.WriteCloser
133
+}
134
+
135
+// frameWriterFactory is an interface to create new frame writer.
136
+type frameWriterFactory interface {
137
+	NewFrameWriter(payloadType byte) (w frameWriter, err error)
138
+}
139
+
140
+type frameHandler interface {
141
+	HandleFrame(frame frameReader) (r frameReader, err error)
142
+	WriteClose(status int) (err error)
143
+}
144
+
145
+// Conn represents a WebSocket connection.
146
+type Conn struct {
147
+	config  *Config
148
+	request *http.Request
149
+
150
+	buf *bufio.ReadWriter
151
+	rwc io.ReadWriteCloser
152
+
153
+	rio sync.Mutex
154
+	frameReaderFactory
155
+	frameReader
156
+
157
+	wio sync.Mutex
158
+	frameWriterFactory
159
+
160
+	frameHandler
161
+	PayloadType        byte
162
+	defaultCloseStatus int
163
+}
164
+
165
+// Read implements the io.Reader interface:
166
+// it reads data of a frame from the WebSocket connection.
167
+// if msg is not large enough for the frame data, it fills the msg and next Read
168
+// will read the rest of the frame data.
169
+// it reads Text frame or Binary frame.
170
+func (ws *Conn) Read(msg []byte) (n int, err error) {
171
+	ws.rio.Lock()
172
+	defer ws.rio.Unlock()
173
+again:
174
+	if ws.frameReader == nil {
175
+		frame, err := ws.frameReaderFactory.NewFrameReader()
176
+		if err != nil {
177
+			return 0, err
178
+		}
179
+		ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
180
+		if err != nil {
181
+			return 0, err
182
+		}
183
+		if ws.frameReader == nil {
184
+			goto again
185
+		}
186
+	}
187
+	n, err = ws.frameReader.Read(msg)
188
+	if err == io.EOF {
189
+		if trailer := ws.frameReader.TrailerReader(); trailer != nil {
190
+			io.Copy(ioutil.Discard, trailer)
191
+		}
192
+		ws.frameReader = nil
193
+		goto again
194
+	}
195
+	return n, err
196
+}
197
+
198
+// Write implements the io.Writer interface:
199
+// it writes data as a frame to the WebSocket connection.
200
+func (ws *Conn) Write(msg []byte) (n int, err error) {
201
+	ws.wio.Lock()
202
+	defer ws.wio.Unlock()
203
+	w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
204
+	if err != nil {
205
+		return 0, err
206
+	}
207
+	n, err = w.Write(msg)
208
+	w.Close()
209
+	if err != nil {
210
+		return n, err
211
+	}
212
+	return n, err
213
+}
214
+
215
+// Close implements the io.Closer interface.
216
+func (ws *Conn) Close() error {
217
+	err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
218
+	err1 := ws.rwc.Close()
219
+	if err != nil {
220
+		return err
221
+	}
222
+	return err1
223
+}
224
+
225
+func (ws *Conn) IsClientConn() bool { return ws.request == nil }
226
+func (ws *Conn) IsServerConn() bool { return ws.request != nil }
227
+
228
+// LocalAddr returns the WebSocket Origin for the connection for client, or
229
+// the WebSocket location for server.
230
+func (ws *Conn) LocalAddr() net.Addr {
231
+	if ws.IsClientConn() {
232
+		return &Addr{ws.config.Origin}
233
+	}
234
+	return &Addr{ws.config.Location}
235
+}
236
+
237
+// RemoteAddr returns the WebSocket location for the connection for client, or
238
+// the Websocket Origin for server.
239
+func (ws *Conn) RemoteAddr() net.Addr {
240
+	if ws.IsClientConn() {
241
+		return &Addr{ws.config.Location}
242
+	}
243
+	return &Addr{ws.config.Origin}
244
+}
245
+
246
+var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
247
+
248
+// SetDeadline sets the connection's network read & write deadlines.
249
+func (ws *Conn) SetDeadline(t time.Time) error {
250
+	if conn, ok := ws.rwc.(net.Conn); ok {
251
+		return conn.SetDeadline(t)
252
+	}
253
+	return errSetDeadline
254
+}
255
+
256
+// SetReadDeadline sets the connection's network read deadline.
257
+func (ws *Conn) SetReadDeadline(t time.Time) error {
258
+	if conn, ok := ws.rwc.(net.Conn); ok {
259
+		return conn.SetReadDeadline(t)
260
+	}
261
+	return errSetDeadline
262
+}
263
+
264
+// SetWriteDeadline sets the connection's network write deadline.
265
+func (ws *Conn) SetWriteDeadline(t time.Time) error {
266
+	if conn, ok := ws.rwc.(net.Conn); ok {
267
+		return conn.SetWriteDeadline(t)
268
+	}
269
+	return errSetDeadline
270
+}
271
+
272
+// Config returns the WebSocket config.
273
+func (ws *Conn) Config() *Config { return ws.config }
274
+
275
+// Request returns the http request upgraded to the WebSocket.
276
+// It is nil for client side.
277
+func (ws *Conn) Request() *http.Request { return ws.request }
278
+
279
+// Codec represents a symmetric pair of functions that implement a codec.
280
+type Codec struct {
281
+	Marshal   func(v interface{}) (data []byte, payloadType byte, err error)
282
+	Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
283
+}
284
+
285
+// Send sends v marshaled by cd.Marshal as single frame to ws.
286
+func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
287
+	data, payloadType, err := cd.Marshal(v)
288
+	if err != nil {
289
+		return err
290
+	}
291
+	ws.wio.Lock()
292
+	defer ws.wio.Unlock()
293
+	w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
294
+	if err != nil {
295
+		return err
296
+	}
297
+	_, err = w.Write(data)
298
+	w.Close()
299
+	return err
300
+}
301
+
302
+// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
303
+func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
304
+	ws.rio.Lock()
305
+	defer ws.rio.Unlock()
306
+	if ws.frameReader != nil {
307
+		_, err = io.Copy(ioutil.Discard, ws.frameReader)
308
+		if err != nil {
309
+			return err
310
+		}
311
+		ws.frameReader = nil
312
+	}
313
+again:
314
+	frame, err := ws.frameReaderFactory.NewFrameReader()
315
+	if err != nil {
316
+		return err
317
+	}
318
+	frame, err = ws.frameHandler.HandleFrame(frame)
319
+	if err != nil {
320
+		return err
321
+	}
322
+	if frame == nil {
323
+		goto again
324
+	}
325
+	payloadType := frame.PayloadType()
326
+	data, err := ioutil.ReadAll(frame)
327
+	if err != nil {
328
+		return err
329
+	}
330
+	return cd.Unmarshal(data, payloadType, v)
331
+}
332
+
333
+func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
334
+	switch data := v.(type) {
335
+	case string:
336
+		return []byte(data), TextFrame, nil
337
+	case []byte:
338
+		return data, BinaryFrame, nil
339
+	}
340
+	return nil, UnknownFrame, ErrNotSupported
341
+}
342
+
343
+func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
344
+	switch data := v.(type) {
345
+	case *string:
346
+		*data = string(msg)
347
+		return nil
348
+	case *[]byte:
349
+		*data = msg
350
+		return nil
351
+	}
352
+	return ErrNotSupported
353
+}
354
+
355
+/*
356
+Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
357
+To send/receive text frame, use string type.
358
+To send/receive binary frame, use []byte type.
359
+
360
+Trivial usage:
361
+
362
+	import "websocket"
363
+
364
+	// receive text frame
365
+	var message string
366
+	websocket.Message.Receive(ws, &message)
367
+
368
+	// send text frame
369
+	message = "hello"
370
+	websocket.Message.Send(ws, message)
371
+
372
+	// receive binary frame
373
+	var data []byte
374
+	websocket.Message.Receive(ws, &data)
375
+
376
+	// send binary frame
377
+	data = []byte{0, 1, 2}
378
+	websocket.Message.Send(ws, data)
379
+
380
+*/
381
+var Message = Codec{marshal, unmarshal}
382
+
383
+func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
384
+	msg, err = json.Marshal(v)
385
+	return msg, TextFrame, err
386
+}
387
+
388
+func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
389
+	return json.Unmarshal(msg, v)
390
+}
391
+
392
+/*
393
+JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
394
+
395
+Trivial usage:
396
+
397
+	import "websocket"
398
+
399
+	type T struct {
400
+		Msg string
401
+		Count int
402
+	}
403
+
404
+	// receive JSON type T
405
+	var data T
406
+	websocket.JSON.Receive(ws, &data)
407
+
408
+	// send JSON type T
409
+	websocket.JSON.Send(ws, data)
410
+*/
411
+var JSON = Codec{jsonMarshal, jsonUnmarshal}