~mark-mims/juju-core/packaging-with-alternatives

« back to all changes in this revision

Viewing changes to src/code.google.com/p/go.net/websocket/websocket.go

  • Committer: Dave Cheney
  • Date: 2013-01-28 10:23:17 UTC
  • Revision ID: david.cheney@canonical.com-20130128102317-fbxahdfoplrglb9m
Add websocket dep to overlay. 

Someone may be able to improve this if they can show me how to do nest a hg repo.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
// The protocol is defined at http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol
 
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
        handshakeData map[string]string
 
91
}
 
92
 
 
93
// serverHandshaker is an interface to handle WebSocket server side handshake.
 
94
type serverHandshaker interface {
 
95
        // ReadHandshake reads handshake request message from client.
 
96
        // Returns http response code and error if any.
 
97
        ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error)
 
98
 
 
99
        // AcceptHandshake accepts the client handshake request and sends
 
100
        // handshake response back to client.
 
101
        AcceptHandshake(buf *bufio.Writer) (err error)
 
102
 
 
103
        // NewServerConn creates a new WebSocket connection.
 
104
        NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
 
105
}
 
106
 
 
107
// frameReader is an interface to read a WebSocket frame.
 
108
type frameReader interface {
 
109
        // Reader is to read payload of the frame.
 
110
        io.Reader
 
111
 
 
112
        // PayloadType returns payload type.
 
113
        PayloadType() byte
 
114
 
 
115
        // HeaderReader returns a reader to read header of the frame.
 
116
        HeaderReader() io.Reader
 
117
 
 
118
        // TrailerReader returns a reader to read trailer of the frame.
 
119
        // If it returns nil, there is no trailer in the frame.
 
120
        TrailerReader() io.Reader
 
121
 
 
122
        // Len returns total length of the frame, including header and trailer.
 
123
        Len() int
 
124
}
 
125
 
 
126
// frameReaderFactory is an interface to creates new frame reader.
 
127
type frameReaderFactory interface {
 
128
        NewFrameReader() (r frameReader, err error)
 
129
}
 
130
 
 
131
// frameWriter is an interface to write a WebSocket frame.
 
132
type frameWriter interface {
 
133
        // Writer is to write playload of the frame.
 
134
        io.WriteCloser
 
135
}
 
136
 
 
137
// frameWriterFactory is an interface to create new frame writer.
 
138
type frameWriterFactory interface {
 
139
        NewFrameWriter(payloadType byte) (w frameWriter, err error)
 
140
}
 
141
 
 
142
type frameHandler interface {
 
143
        HandleFrame(frame frameReader) (r frameReader, err error)
 
144
        WriteClose(status int) (err error)
 
145
}
 
146
 
 
147
// Conn represents a WebSocket connection.
 
148
type Conn struct {
 
149
        config  *Config
 
150
        request *http.Request
 
151
 
 
152
        buf *bufio.ReadWriter
 
153
        rwc io.ReadWriteCloser
 
154
 
 
155
        rio sync.Mutex
 
156
        frameReaderFactory
 
157
        frameReader
 
158
 
 
159
        wio sync.Mutex
 
160
        frameWriterFactory
 
161
 
 
162
        frameHandler
 
163
        PayloadType        byte
 
164
        defaultCloseStatus int
 
165
}
 
166
 
 
167
// Read implements the io.Reader interface:
 
168
// it reads data of a frame from the WebSocket connection.
 
169
// if msg is not large enough for the frame data, it fills the msg and next Read
 
170
// will read the rest of the frame data.
 
171
// it reads Text frame or Binary frame.
 
172
func (ws *Conn) Read(msg []byte) (n int, err error) {
 
173
        ws.rio.Lock()
 
174
        defer ws.rio.Unlock()
 
175
again:
 
176
        if ws.frameReader == nil {
 
177
                frame, err := ws.frameReaderFactory.NewFrameReader()
 
178
                if err != nil {
 
179
                        return 0, err
 
180
                }
 
181
                ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
 
182
                if err != nil {
 
183
                        return 0, err
 
184
                }
 
185
                if ws.frameReader == nil {
 
186
                        goto again
 
187
                }
 
188
        }
 
189
        n, err = ws.frameReader.Read(msg)
 
190
        if err == io.EOF {
 
191
                if trailer := ws.frameReader.TrailerReader(); trailer != nil {
 
192
                        io.Copy(ioutil.Discard, trailer)
 
193
                }
 
194
                ws.frameReader = nil
 
195
                goto again
 
196
        }
 
197
        return n, err
 
198
}
 
199
 
 
200
// Write implements the io.Writer interface:
 
201
// it writes data as a frame to the WebSocket connection.
 
202
func (ws *Conn) Write(msg []byte) (n int, err error) {
 
203
        ws.wio.Lock()
 
204
        defer ws.wio.Unlock()
 
205
        w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
 
206
        if err != nil {
 
207
                return 0, err
 
208
        }
 
209
        n, err = w.Write(msg)
 
210
        w.Close()
 
211
        if err != nil {
 
212
                return n, err
 
213
        }
 
214
        return n, err
 
215
}
 
216
 
 
217
// Close implements the io.Closer interface.
 
218
func (ws *Conn) Close() error {
 
219
        err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
 
220
        if err != nil {
 
221
                return err
 
222
        }
 
223
        return ws.rwc.Close()
 
224
}
 
225
 
 
226
func (ws *Conn) IsClientConn() bool { return ws.request == nil }
 
227
func (ws *Conn) IsServerConn() bool { return ws.request != nil }
 
228
 
 
229
// LocalAddr returns the WebSocket Origin for the connection for client, or
 
230
// the WebSocket location for server.
 
231
func (ws *Conn) LocalAddr() net.Addr {
 
232
        if ws.IsClientConn() {
 
233
                return &Addr{ws.config.Origin}
 
234
        }
 
235
        return &Addr{ws.config.Location}
 
236
}
 
237
 
 
238
// RemoteAddr returns the WebSocket location for the connection for client, or
 
239
// the Websocket Origin for server.
 
240
func (ws *Conn) RemoteAddr() net.Addr {
 
241
        if ws.IsClientConn() {
 
242
                return &Addr{ws.config.Location}
 
243
        }
 
244
        return &Addr{ws.config.Origin}
 
245
}
 
246
 
 
247
var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
 
248
 
 
249
// SetDeadline sets the connection's network read & write deadlines.
 
250
func (ws *Conn) SetDeadline(t time.Time) error {
 
251
        if conn, ok := ws.rwc.(net.Conn); ok {
 
252
                return conn.SetDeadline(t)
 
253
        }
 
254
        return errSetDeadline
 
255
}
 
256
 
 
257
// SetReadDeadline sets the connection's network read deadline.
 
258
func (ws *Conn) SetReadDeadline(t time.Time) error {
 
259
        if conn, ok := ws.rwc.(net.Conn); ok {
 
260
                return conn.SetReadDeadline(t)
 
261
        }
 
262
        return errSetDeadline
 
263
}
 
264
 
 
265
// SetWriteDeadline sets the connection's network write deadline.
 
266
func (ws *Conn) SetWriteDeadline(t time.Time) error {
 
267
        if conn, ok := ws.rwc.(net.Conn); ok {
 
268
                return conn.SetWriteDeadline(t)
 
269
        }
 
270
        return errSetDeadline
 
271
}
 
272
 
 
273
// Config returns the WebSocket config.
 
274
func (ws *Conn) Config() *Config { return ws.config }
 
275
 
 
276
// Request returns the http request upgraded to the WebSocket.
 
277
// It is nil for client side.
 
278
func (ws *Conn) Request() *http.Request { return ws.request }
 
279
 
 
280
// Codec represents a symmetric pair of functions that implement a codec.
 
281
type Codec struct {
 
282
        Marshal   func(v interface{}) (data []byte, payloadType byte, err error)
 
283
        Unmarshal func(data []byte, payloadType byte, v interface{}) (err error)
 
284
}
 
285
 
 
286
// Send sends v marshaled by cd.Marshal as single frame to ws.
 
287
func (cd Codec) Send(ws *Conn, v interface{}) (err error) {
 
288
        data, payloadType, err := cd.Marshal(v)
 
289
        if err != nil {
 
290
                return err
 
291
        }
 
292
        ws.wio.Lock()
 
293
        defer ws.wio.Unlock()
 
294
        w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
 
295
        if err != nil {
 
296
                return err
 
297
        }
 
298
        _, err = w.Write(data)
 
299
        w.Close()
 
300
        return err
 
301
}
 
302
 
 
303
// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
 
304
func (cd Codec) Receive(ws *Conn, v interface{}) (err error) {
 
305
        ws.rio.Lock()
 
306
        defer ws.rio.Unlock()
 
307
        if ws.frameReader != nil {
 
308
                _, err = io.Copy(ioutil.Discard, ws.frameReader)
 
309
                if err != nil {
 
310
                        return err
 
311
                }
 
312
                ws.frameReader = nil
 
313
        }
 
314
again:
 
315
        frame, err := ws.frameReaderFactory.NewFrameReader()
 
316
        if err != nil {
 
317
                return err
 
318
        }
 
319
        frame, err = ws.frameHandler.HandleFrame(frame)
 
320
        if err != nil {
 
321
                return err
 
322
        }
 
323
        if frame == nil {
 
324
                goto again
 
325
        }
 
326
        payloadType := frame.PayloadType()
 
327
        data, err := ioutil.ReadAll(frame)
 
328
        if err != nil {
 
329
                return err
 
330
        }
 
331
        return cd.Unmarshal(data, payloadType, v)
 
332
}
 
333
 
 
334
func marshal(v interface{}) (msg []byte, payloadType byte, err error) {
 
335
        switch data := v.(type) {
 
336
        case string:
 
337
                return []byte(data), TextFrame, nil
 
338
        case []byte:
 
339
                return data, BinaryFrame, nil
 
340
        }
 
341
        return nil, UnknownFrame, ErrNotSupported
 
342
}
 
343
 
 
344
func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
 
345
        switch data := v.(type) {
 
346
        case *string:
 
347
                *data = string(msg)
 
348
                return nil
 
349
        case *[]byte:
 
350
                *data = msg
 
351
                return nil
 
352
        }
 
353
        return ErrNotSupported
 
354
}
 
355
 
 
356
/*
 
357
Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
 
358
To send/receive text frame, use string type.
 
359
To send/receive binary frame, use []byte type.
 
360
 
 
361
Trivial usage:
 
362
 
 
363
        import "websocket"
 
364
 
 
365
        // receive text frame
 
366
        var message string
 
367
        websocket.Message.Receive(ws, &message)
 
368
 
 
369
        // send text frame
 
370
        message = "hello"
 
371
        websocket.Message.Send(ws, message)
 
372
 
 
373
        // receive binary frame
 
374
        var data []byte
 
375
        websocket.Message.Receive(ws, &data)
 
376
 
 
377
        // send binary frame
 
378
        data = []byte{0, 1, 2}
 
379
        websocket.Message.Send(ws, data)
 
380
 
 
381
*/
 
382
var Message = Codec{marshal, unmarshal}
 
383
 
 
384
func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) {
 
385
        msg, err = json.Marshal(v)
 
386
        return msg, TextFrame, err
 
387
}
 
388
 
 
389
func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) {
 
390
        return json.Unmarshal(msg, v)
 
391
}
 
392
 
 
393
/*
 
394
JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
 
395
 
 
396
Trivial usage:
 
397
 
 
398
        import "websocket"
 
399
 
 
400
        type T struct {
 
401
                Msg string
 
402
                Count int
 
403
        }
 
404
 
 
405
        // receive JSON type T
 
406
        var data T
 
407
        websocket.JSON.Receive(ws, &data)
 
408
 
 
409
        // send JSON type T
 
410
        websocket.JSON.Send(ws, data)
 
411
*/
 
412
var JSON = Codec{jsonMarshal, jsonUnmarshal}