github.com/technosophos/deis@v1.7.1-0.20150915173815-f9005256004b/Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go (about) 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 ProtocolVersionHybi13 = 13 25 ProtocolVersionHybi = ProtocolVersionHybi13 26 SupportedProtocolVersion = "13" 27 28 ContinuationFrame = 0 29 TextFrame = 1 30 BinaryFrame = 2 31 CloseFrame = 8 32 PingFrame = 9 33 PongFrame = 10 34 UnknownFrame = 255 35 ) 36 37 // ProtocolError represents WebSocket protocol errors. 38 type ProtocolError struct { 39 ErrorString string 40 } 41 42 func (err *ProtocolError) Error() string { return err.ErrorString } 43 44 var ( 45 ErrBadProtocolVersion = &ProtocolError{"bad protocol version"} 46 ErrBadScheme = &ProtocolError{"bad scheme"} 47 ErrBadStatus = &ProtocolError{"bad status"} 48 ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"} 49 ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"} 50 ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"} 51 ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"} 52 ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"} 53 ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"} 54 ErrBadFrame = &ProtocolError{"bad frame"} 55 ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"} 56 ErrNotWebSocket = &ProtocolError{"not websocket protocol"} 57 ErrBadRequestMethod = &ProtocolError{"bad method"} 58 ErrNotSupported = &ProtocolError{"not supported"} 59 ) 60 61 // Addr is an implementation of net.Addr for WebSocket. 62 type Addr struct { 63 *url.URL 64 } 65 66 // Network returns the network type for a WebSocket, "websocket". 67 func (addr *Addr) Network() string { return "websocket" } 68 69 // Config is a WebSocket configuration 70 type Config struct { 71 // A WebSocket server address. 72 Location *url.URL 73 74 // A Websocket client origin. 75 Origin *url.URL 76 77 // WebSocket subprotocols. 78 Protocol []string 79 80 // WebSocket protocol version. 81 Version int 82 83 // TLS config for secure WebSocket (wss). 84 TlsConfig *tls.Config 85 86 // Additional header fields to be sent in WebSocket opening handshake. 87 Header http.Header 88 89 handshakeData map[string]string 90 } 91 92 // serverHandshaker is an interface to handle WebSocket server side handshake. 93 type serverHandshaker interface { 94 // ReadHandshake reads handshake request message from client. 95 // Returns http response code and error if any. 96 ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) 97 98 // AcceptHandshake accepts the client handshake request and sends 99 // handshake response back to client. 100 AcceptHandshake(buf *bufio.Writer) (err error) 101 102 // NewServerConn creates a new WebSocket connection. 103 NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) 104 } 105 106 // frameReader is an interface to read a WebSocket frame. 107 type frameReader interface { 108 // Reader is to read payload of the frame. 109 io.Reader 110 111 // PayloadType returns payload type. 112 PayloadType() byte 113 114 // HeaderReader returns a reader to read header of the frame. 115 HeaderReader() io.Reader 116 117 // TrailerReader returns a reader to read trailer of the frame. 118 // If it returns nil, there is no trailer in the frame. 119 TrailerReader() io.Reader 120 121 // Len returns total length of the frame, including header and trailer. 122 Len() int 123 } 124 125 // frameReaderFactory is an interface to creates new frame reader. 126 type frameReaderFactory interface { 127 NewFrameReader() (r frameReader, err error) 128 } 129 130 // frameWriter is an interface to write a WebSocket frame. 131 type frameWriter interface { 132 // Writer is to write payload of the frame. 133 io.WriteCloser 134 } 135 136 // frameWriterFactory is an interface to create new frame writer. 137 type frameWriterFactory interface { 138 NewFrameWriter(payloadType byte) (w frameWriter, err error) 139 } 140 141 type frameHandler interface { 142 HandleFrame(frame frameReader) (r frameReader, err error) 143 WriteClose(status int) (err error) 144 } 145 146 // Conn represents a WebSocket connection. 147 type Conn struct { 148 config *Config 149 request *http.Request 150 151 buf *bufio.ReadWriter 152 rwc io.ReadWriteCloser 153 154 rio sync.Mutex 155 frameReaderFactory 156 frameReader 157 158 wio sync.Mutex 159 frameWriterFactory 160 161 frameHandler 162 PayloadType byte 163 defaultCloseStatus int 164 } 165 166 // Read implements the io.Reader interface: 167 // it reads data of a frame from the WebSocket connection. 168 // if msg is not large enough for the frame data, it fills the msg and next Read 169 // will read the rest of the frame data. 170 // it reads Text frame or Binary frame. 171 func (ws *Conn) Read(msg []byte) (n int, err error) { 172 ws.rio.Lock() 173 defer ws.rio.Unlock() 174 again: 175 if ws.frameReader == nil { 176 frame, err := ws.frameReaderFactory.NewFrameReader() 177 if err != nil { 178 return 0, err 179 } 180 ws.frameReader, err = ws.frameHandler.HandleFrame(frame) 181 if err != nil { 182 return 0, err 183 } 184 if ws.frameReader == nil { 185 goto again 186 } 187 } 188 n, err = ws.frameReader.Read(msg) 189 if err == io.EOF { 190 if trailer := ws.frameReader.TrailerReader(); trailer != nil { 191 io.Copy(ioutil.Discard, trailer) 192 } 193 ws.frameReader = nil 194 goto again 195 } 196 return n, err 197 } 198 199 // Write implements the io.Writer interface: 200 // it writes data as a frame to the WebSocket connection. 201 func (ws *Conn) Write(msg []byte) (n int, err error) { 202 ws.wio.Lock() 203 defer ws.wio.Unlock() 204 w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType) 205 if err != nil { 206 return 0, err 207 } 208 n, err = w.Write(msg) 209 w.Close() 210 if err != nil { 211 return n, err 212 } 213 return n, err 214 } 215 216 // Close implements the io.Closer interface. 217 func (ws *Conn) Close() error { 218 err := ws.frameHandler.WriteClose(ws.defaultCloseStatus) 219 err1 := ws.rwc.Close() 220 if err != nil { 221 return err 222 } 223 return err1 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}