~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/golang.org/x/net/websocket/hybi.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
                if lengthFields == 8 && i == 0 { // MSB must be zero when 7+64 bits
 
161
                        b &= 0x7f
 
162
                }
 
163
                header = append(header, b)
 
164
                hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
 
165
        }
 
166
        if mask {
 
167
                // Masking key. 4 bytes.
 
168
                for i := 0; i < 4; i++ {
 
169
                        b, err = buf.ReadByte()
 
170
                        if err != nil {
 
171
                                return
 
172
                        }
 
173
                        header = append(header, b)
 
174
                        hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
 
175
                }
 
176
        }
 
177
        hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
 
178
        hybiFrame.header.data = bytes.NewBuffer(header)
 
179
        hybiFrame.length = len(header) + int(hybiFrame.header.Length)
 
180
        return
 
181
}
 
182
 
 
183
// A HybiFrameWriter is a writer for hybi frame.
 
184
type hybiFrameWriter struct {
 
185
        writer *bufio.Writer
 
186
 
 
187
        header *hybiFrameHeader
 
188
}
 
189
 
 
190
func (frame *hybiFrameWriter) Write(msg []byte) (n int, err error) {
 
191
        var header []byte
 
192
        var b byte
 
193
        if frame.header.Fin {
 
194
                b |= 0x80
 
195
        }
 
196
        for i := 0; i < 3; i++ {
 
197
                if frame.header.Rsv[i] {
 
198
                        j := uint(6 - i)
 
199
                        b |= 1 << j
 
200
                }
 
201
        }
 
202
        b |= frame.header.OpCode
 
203
        header = append(header, b)
 
204
        if frame.header.MaskingKey != nil {
 
205
                b = 0x80
 
206
        } else {
 
207
                b = 0
 
208
        }
 
209
        lengthFields := 0
 
210
        length := len(msg)
 
211
        switch {
 
212
        case length <= 125:
 
213
                b |= byte(length)
 
214
        case length < 65536:
 
215
                b |= 126
 
216
                lengthFields = 2
 
217
        default:
 
218
                b |= 127
 
219
                lengthFields = 8
 
220
        }
 
221
        header = append(header, b)
 
222
        for i := 0; i < lengthFields; i++ {
 
223
                j := uint((lengthFields - i - 1) * 8)
 
224
                b = byte((length >> j) & 0xff)
 
225
                header = append(header, b)
 
226
        }
 
227
        if frame.header.MaskingKey != nil {
 
228
                if len(frame.header.MaskingKey) != 4 {
 
229
                        return 0, ErrBadMaskingKey
 
230
                }
 
231
                header = append(header, frame.header.MaskingKey...)
 
232
                frame.writer.Write(header)
 
233
                data := make([]byte, length)
 
234
                for i := range data {
 
235
                        data[i] = msg[i] ^ frame.header.MaskingKey[i%4]
 
236
                }
 
237
                frame.writer.Write(data)
 
238
                err = frame.writer.Flush()
 
239
                return length, err
 
240
        }
 
241
        frame.writer.Write(header)
 
242
        frame.writer.Write(msg)
 
243
        err = frame.writer.Flush()
 
244
        return length, err
 
245
}
 
246
 
 
247
func (frame *hybiFrameWriter) Close() error { return nil }
 
248
 
 
249
type hybiFrameWriterFactory struct {
 
250
        *bufio.Writer
 
251
        needMaskingKey bool
 
252
}
 
253
 
 
254
func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) {
 
255
        frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
 
256
        if buf.needMaskingKey {
 
257
                frameHeader.MaskingKey, err = generateMaskingKey()
 
258
                if err != nil {
 
259
                        return nil, err
 
260
                }
 
261
        }
 
262
        return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
 
263
}
 
264
 
 
265
type hybiFrameHandler struct {
 
266
        conn        *Conn
 
267
        payloadType byte
 
268
}
 
269
 
 
270
func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (frameReader, error) {
 
271
        if handler.conn.IsServerConn() {
 
272
                // The client MUST mask all frames sent to the server.
 
273
                if frame.(*hybiFrameReader).header.MaskingKey == nil {
 
274
                        handler.WriteClose(closeStatusProtocolError)
 
275
                        return nil, io.EOF
 
276
                }
 
277
        } else {
 
278
                // The server MUST NOT mask all frames.
 
279
                if frame.(*hybiFrameReader).header.MaskingKey != nil {
 
280
                        handler.WriteClose(closeStatusProtocolError)
 
281
                        return nil, io.EOF
 
282
                }
 
283
        }
 
284
        if header := frame.HeaderReader(); header != nil {
 
285
                io.Copy(ioutil.Discard, header)
 
286
        }
 
287
        switch frame.PayloadType() {
 
288
        case ContinuationFrame:
 
289
                frame.(*hybiFrameReader).header.OpCode = handler.payloadType
 
290
        case TextFrame, BinaryFrame:
 
291
                handler.payloadType = frame.PayloadType()
 
292
        case CloseFrame:
 
293
                return nil, io.EOF
 
294
        case PingFrame, PongFrame:
 
295
                b := make([]byte, maxControlFramePayloadLength)
 
296
                n, err := io.ReadFull(frame, b)
 
297
                if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
 
298
                        return nil, err
 
299
                }
 
300
                io.Copy(ioutil.Discard, frame)
 
301
                if frame.PayloadType() == PingFrame {
 
302
                        if _, err := handler.WritePong(b[:n]); err != nil {
 
303
                                return nil, err
 
304
                        }
 
305
                }
 
306
                return nil, nil
 
307
        }
 
308
        return frame, nil
 
309
}
 
310
 
 
311
func (handler *hybiFrameHandler) WriteClose(status int) (err error) {
 
312
        handler.conn.wio.Lock()
 
313
        defer handler.conn.wio.Unlock()
 
314
        w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
 
315
        if err != nil {
 
316
                return err
 
317
        }
 
318
        msg := make([]byte, 2)
 
319
        binary.BigEndian.PutUint16(msg, uint16(status))
 
320
        _, err = w.Write(msg)
 
321
        w.Close()
 
322
        return err
 
323
}
 
324
 
 
325
func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err error) {
 
326
        handler.conn.wio.Lock()
 
327
        defer handler.conn.wio.Unlock()
 
328
        w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
 
329
        if err != nil {
 
330
                return 0, err
 
331
        }
 
332
        n, err = w.Write(msg)
 
333
        w.Close()
 
334
        return n, err
 
335
}
 
336
 
 
337
// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
 
338
func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
 
339
        if buf == nil {
 
340
                br := bufio.NewReader(rwc)
 
341
                bw := bufio.NewWriter(rwc)
 
342
                buf = bufio.NewReadWriter(br, bw)
 
343
        }
 
344
        ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
 
345
                frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
 
346
                frameWriterFactory: hybiFrameWriterFactory{
 
347
                        buf.Writer, request == nil},
 
348
                PayloadType:        TextFrame,
 
349
                defaultCloseStatus: closeStatusNormal}
 
350
        ws.frameHandler = &hybiFrameHandler{conn: ws}
 
351
        return ws
 
352
}
 
353
 
 
354
// generateMaskingKey generates a masking key for a frame.
 
355
func generateMaskingKey() (maskingKey []byte, err error) {
 
356
        maskingKey = make([]byte, 4)
 
357
        if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
 
358
                return
 
359
        }
 
360
        return
 
361
}
 
362
 
 
363
// generateNonce generates a nonce consisting of a randomly selected 16-byte
 
364
// value that has been base64-encoded.
 
365
func generateNonce() (nonce []byte) {
 
366
        key := make([]byte, 16)
 
367
        if _, err := io.ReadFull(rand.Reader, key); err != nil {
 
368
                panic(err)
 
369
        }
 
370
        nonce = make([]byte, 24)
 
371
        base64.StdEncoding.Encode(nonce, key)
 
372
        return
 
373
}
 
374
 
 
375
// removeZone removes IPv6 zone identifer from host.
 
376
// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
 
377
func removeZone(host string) string {
 
378
        if !strings.HasPrefix(host, "[") {
 
379
                return host
 
380
        }
 
381
        i := strings.LastIndex(host, "]")
 
382
        if i < 0 {
 
383
                return host
 
384
        }
 
385
        j := strings.LastIndex(host[:i], "%")
 
386
        if j < 0 {
 
387
                return host
 
388
        }
 
389
        return host[:j] + host[i:]
 
390
}
 
391
 
 
392
// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
 
393
// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
 
394
func getNonceAccept(nonce []byte) (expected []byte, err error) {
 
395
        h := sha1.New()
 
396
        if _, err = h.Write(nonce); err != nil {
 
397
                return
 
398
        }
 
399
        if _, err = h.Write([]byte(websocketGUID)); err != nil {
 
400
                return
 
401
        }
 
402
        expected = make([]byte, 28)
 
403
        base64.StdEncoding.Encode(expected, h.Sum(nil))
 
404
        return
 
405
}
 
406
 
 
407
// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
 
408
func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
 
409
        bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
 
410
 
 
411
        // According to RFC 6874, an HTTP client, proxy, or other
 
412
        // intermediary must remove any IPv6 zone identifier attached
 
413
        // to an outgoing URI.
 
414
        bw.WriteString("Host: " + removeZone(config.Location.Host) + "\r\n")
 
415
        bw.WriteString("Upgrade: websocket\r\n")
 
416
        bw.WriteString("Connection: Upgrade\r\n")
 
417
        nonce := generateNonce()
 
418
        if config.handshakeData != nil {
 
419
                nonce = []byte(config.handshakeData["key"])
 
420
        }
 
421
        bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
 
422
        bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
 
423
 
 
424
        if config.Version != ProtocolVersionHybi13 {
 
425
                return ErrBadProtocolVersion
 
426
        }
 
427
 
 
428
        bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
 
429
        if len(config.Protocol) > 0 {
 
430
                bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
 
431
        }
 
432
        // TODO(ukai): send Sec-WebSocket-Extensions.
 
433
        err = config.Header.WriteSubset(bw, handshakeHeader)
 
434
        if err != nil {
 
435
                return err
 
436
        }
 
437
 
 
438
        bw.WriteString("\r\n")
 
439
        if err = bw.Flush(); err != nil {
 
440
                return err
 
441
        }
 
442
 
 
443
        resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
 
444
        if err != nil {
 
445
                return err
 
446
        }
 
447
        if resp.StatusCode != 101 {
 
448
                return ErrBadStatus
 
449
        }
 
450
        if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
 
451
                strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
 
452
                return ErrBadUpgrade
 
453
        }
 
454
        expectedAccept, err := getNonceAccept(nonce)
 
455
        if err != nil {
 
456
                return err
 
457
        }
 
458
        if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
 
459
                return ErrChallengeResponse
 
460
        }
 
461
        if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
 
462
                return ErrUnsupportedExtensions
 
463
        }
 
464
        offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
 
465
        if offeredProtocol != "" {
 
466
                protocolMatched := false
 
467
                for i := 0; i < len(config.Protocol); i++ {
 
468
                        if config.Protocol[i] == offeredProtocol {
 
469
                                protocolMatched = true
 
470
                                break
 
471
                        }
 
472
                }
 
473
                if !protocolMatched {
 
474
                        return ErrBadWebSocketProtocol
 
475
                }
 
476
                config.Protocol = []string{offeredProtocol}
 
477
        }
 
478
 
 
479
        return nil
 
480
}
 
481
 
 
482
// newHybiClientConn creates a client WebSocket connection after handshake.
 
483
func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
 
484
        return newHybiConn(config, buf, rwc, nil)
 
485
}
 
486
 
 
487
// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
 
488
type hybiServerHandshaker struct {
 
489
        *Config
 
490
        accept []byte
 
491
}
 
492
 
 
493
func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) {
 
494
        c.Version = ProtocolVersionHybi13
 
495
        if req.Method != "GET" {
 
496
                return http.StatusMethodNotAllowed, ErrBadRequestMethod
 
497
        }
 
498
        // HTTP version can be safely ignored.
 
499
 
 
500
        if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
 
501
                !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
 
502
                return http.StatusBadRequest, ErrNotWebSocket
 
503
        }
 
504
 
 
505
        key := req.Header.Get("Sec-Websocket-Key")
 
506
        if key == "" {
 
507
                return http.StatusBadRequest, ErrChallengeResponse
 
508
        }
 
509
        version := req.Header.Get("Sec-Websocket-Version")
 
510
        switch version {
 
511
        case "13":
 
512
                c.Version = ProtocolVersionHybi13
 
513
        default:
 
514
                return http.StatusBadRequest, ErrBadWebSocketVersion
 
515
        }
 
516
        var scheme string
 
517
        if req.TLS != nil {
 
518
                scheme = "wss"
 
519
        } else {
 
520
                scheme = "ws"
 
521
        }
 
522
        c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI())
 
523
        if err != nil {
 
524
                return http.StatusBadRequest, err
 
525
        }
 
526
        protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
 
527
        if protocol != "" {
 
528
                protocols := strings.Split(protocol, ",")
 
529
                for i := 0; i < len(protocols); i++ {
 
530
                        c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
 
531
                }
 
532
        }
 
533
        c.accept, err = getNonceAccept([]byte(key))
 
534
        if err != nil {
 
535
                return http.StatusInternalServerError, err
 
536
        }
 
537
        return http.StatusSwitchingProtocols, nil
 
538
}
 
539
 
 
540
// Origin parses the Origin header in req.
 
541
// If the Origin header is not set, it returns nil and nil.
 
542
func Origin(config *Config, req *http.Request) (*url.URL, error) {
 
543
        var origin string
 
544
        switch config.Version {
 
545
        case ProtocolVersionHybi13:
 
546
                origin = req.Header.Get("Origin")
 
547
        }
 
548
        if origin == "" {
 
549
                return nil, nil
 
550
        }
 
551
        return url.ParseRequestURI(origin)
 
552
}
 
553
 
 
554
func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) {
 
555
        if len(c.Protocol) > 0 {
 
556
                if len(c.Protocol) != 1 {
 
557
                        // You need choose a Protocol in Handshake func in Server.
 
558
                        return ErrBadWebSocketProtocol
 
559
                }
 
560
        }
 
561
        buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
 
562
        buf.WriteString("Upgrade: websocket\r\n")
 
563
        buf.WriteString("Connection: Upgrade\r\n")
 
564
        buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
 
565
        if len(c.Protocol) > 0 {
 
566
                buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
 
567
        }
 
568
        // TODO(ukai): send Sec-WebSocket-Extensions.
 
569
        if c.Header != nil {
 
570
                err := c.Header.WriteSubset(buf, handshakeHeader)
 
571
                if err != nil {
 
572
                        return err
 
573
                }
 
574
        }
 
575
        buf.WriteString("\r\n")
 
576
        return buf.Flush()
 
577
}
 
578
 
 
579
func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
 
580
        return newHybiServerConn(c.Config, buf, rwc, request)
 
581
}
 
582
 
 
583
// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
 
584
func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
 
585
        return newHybiConn(config, buf, rwc, request)
 
586
}