mirror of https://github.com/gorilla/websocket.git
Merge branch 'master' of github.com:imkira/websocket into fixHeaderCase
This commit is contained in:
commit
9afdfba08c
|
@ -30,8 +30,8 @@ subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn
|
|||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th><a href="http://godoc.org/github.com/gorilla/websocket">gorilla</a></th>
|
||||
<th><a href="http://godoc.org/code.google.com/p/go.net/websocket">go.net</a></th>
|
||||
<th><a href="http://godoc.org/github.com/gorilla/websocket">github.com/gorilla</a></th>
|
||||
<th><a href="http://godoc.org/golang.org/x/net/websocket">golang.org/x/net</a></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr><td colspan="3"><a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a> Features</td></tr>
|
||||
|
@ -50,10 +50,10 @@ Notes:
|
|||
|
||||
1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html).
|
||||
2. The application can get the type of a received data message by implementing
|
||||
a [Codec marshal](http://godoc.org/code.google.com/p/go.net/websocket#Codec.Marshal)
|
||||
a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal)
|
||||
function.
|
||||
3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries.
|
||||
Read returns when the input buffer is full or a frame boundary is
|
||||
encountered, Each call to Write sends a single frame message. The Gorilla
|
||||
encountered. Each call to Write sends a single frame message. The Gorilla
|
||||
io.Reader and io.WriteCloser operate on a single WebSocket message.
|
||||
|
||||
|
|
12
client.go
12
client.go
|
@ -215,16 +215,6 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
|||
}
|
||||
}
|
||||
|
||||
readBufferSize := d.ReadBufferSize
|
||||
if readBufferSize == 0 {
|
||||
readBufferSize = 4096
|
||||
}
|
||||
|
||||
writeBufferSize := d.WriteBufferSize
|
||||
if writeBufferSize == 0 {
|
||||
writeBufferSize = 4096
|
||||
}
|
||||
|
||||
if len(d.Subprotocols) > 0 {
|
||||
h := http.Header{}
|
||||
for k, v := range requestHeader {
|
||||
|
@ -234,7 +224,7 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
|||
requestHeader = h
|
||||
}
|
||||
|
||||
conn, resp, err := NewClient(netConn, u, requestHeader, readBufferSize, writeBufferSize)
|
||||
conn, resp, err := NewClient(netConn, u, requestHeader, d.ReadBufferSize, d.WriteBufferSize)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
|
96
conn.go
96
conn.go
|
@ -16,6 +16,20 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
maxFrameHeaderSize = 2 + 8 + 4 // Fixed header + length + mask
|
||||
maxControlFramePayloadSize = 125
|
||||
finalBit = 1 << 7
|
||||
maskBit = 1 << 7
|
||||
writeWait = time.Second
|
||||
|
||||
defaultReadBufferSize = 4096
|
||||
defaultWriteBufferSize = 4096
|
||||
|
||||
continuationFrame = 0
|
||||
noFrame = -1
|
||||
)
|
||||
|
||||
// Close codes defined in RFC 6455, section 11.7.
|
||||
const (
|
||||
CloseNormalClosure = 1000
|
||||
|
@ -55,49 +69,46 @@ const (
|
|||
PongMessage = 10
|
||||
)
|
||||
|
||||
var (
|
||||
continuationFrame = 0
|
||||
noFrame = -1
|
||||
)
|
||||
// ErrCloseSent is returned when the application writes a message to the
|
||||
// connection after sending a close message.
|
||||
var ErrCloseSent = errors.New("websocket: close sent")
|
||||
|
||||
var (
|
||||
// ErrCloseSent is returned when the application writes a message to the
|
||||
// connection after sending a close message.
|
||||
ErrCloseSent = errors.New("websocket: close sent")
|
||||
// ErrReadLimit is returned when reading a message that is larger than the
|
||||
// read limit set for the connection.
|
||||
var ErrReadLimit = errors.New("websocket: read limit exceeded")
|
||||
|
||||
// ErrReadLimit is returned when reading a message that is larger than the
|
||||
// read limit set for the connection.
|
||||
ErrReadLimit = errors.New("websocket: read limit exceeded")
|
||||
)
|
||||
|
||||
type websocketError struct {
|
||||
// netError satisfies the net Error interface.
|
||||
type netError struct {
|
||||
msg string
|
||||
temporary bool
|
||||
timeout bool
|
||||
}
|
||||
|
||||
func (e *websocketError) Error() string { return e.msg }
|
||||
func (e *websocketError) Temporary() bool { return e.temporary }
|
||||
func (e *websocketError) Timeout() bool { return e.timeout }
|
||||
func (e *netError) Error() string { return e.msg }
|
||||
func (e *netError) Temporary() bool { return e.temporary }
|
||||
func (e *netError) Timeout() bool { return e.timeout }
|
||||
|
||||
// closeError represents close frame.
|
||||
type closeError struct {
|
||||
code int
|
||||
text string
|
||||
}
|
||||
|
||||
func (e *closeError) Error() string {
|
||||
return "websocket: close " + strconv.Itoa(e.code) + " " + e.text
|
||||
}
|
||||
|
||||
var (
|
||||
errWriteTimeout = &websocketError{msg: "websocket: write timeout", timeout: true}
|
||||
errWriteTimeout = &netError{msg: "websocket: write timeout", timeout: true}
|
||||
errUnexpectedEOF = &closeError{code: CloseAbnormalClosure, text: io.ErrUnexpectedEOF.Error()}
|
||||
errBadWriteOpCode = errors.New("websocket: bad write message type")
|
||||
errWriteClosed = errors.New("websocket: write closed")
|
||||
errInvalidControlFrame = errors.New("websocket: invalid control frame")
|
||||
)
|
||||
|
||||
const (
|
||||
maxFrameHeaderSize = 2 + 8 + 4 // Fixed header + length + mask
|
||||
maxControlFramePayloadSize = 125
|
||||
finalBit = 1 << 7
|
||||
maskBit = 1 << 7
|
||||
writeWait = time.Second
|
||||
)
|
||||
|
||||
func hideTempErr(err error) error {
|
||||
if e, ok := err.(net.Error); ok && e.Temporary() {
|
||||
err = struct{ error }{err}
|
||||
err = &netError{msg: e.Error(), timeout: e.Timeout()}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -155,17 +166,24 @@ type Conn struct {
|
|||
handlePing func(string) error
|
||||
}
|
||||
|
||||
func newConn(conn net.Conn, isServer bool, readBufSize, writeBufSize int) *Conn {
|
||||
func newConn(conn net.Conn, isServer bool, readBufferSize, writeBufferSize int) *Conn {
|
||||
mu := make(chan bool, 1)
|
||||
mu <- true
|
||||
|
||||
if readBufferSize == 0 {
|
||||
readBufferSize = defaultReadBufferSize
|
||||
}
|
||||
if writeBufferSize == 0 {
|
||||
writeBufferSize = defaultWriteBufferSize
|
||||
}
|
||||
|
||||
c := &Conn{
|
||||
isServer: isServer,
|
||||
br: bufio.NewReaderSize(conn, readBufSize),
|
||||
br: bufio.NewReaderSize(conn, readBufferSize),
|
||||
conn: conn,
|
||||
mu: mu,
|
||||
readFinal: true,
|
||||
writeBuf: make([]byte, writeBufSize+maxFrameHeaderSize),
|
||||
writeBuf: make([]byte, writeBufferSize+maxFrameHeaderSize),
|
||||
writeFrameType: noFrame,
|
||||
writePos: maxFrameHeaderSize,
|
||||
}
|
||||
|
@ -508,7 +526,7 @@ func (c *Conn) WriteMessage(messageType int, data []byte) error {
|
|||
// SetWriteDeadline sets the write deadline on the underlying network
|
||||
// connection. After a write has timed out, the websocket state is corrupt and
|
||||
// all future writes will return an error. A zero value for t means writes will
|
||||
// not time out
|
||||
// not time out.
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
c.writeDeadline = t
|
||||
return nil
|
||||
|
@ -527,7 +545,7 @@ func (c *Conn) readFull(p []byte) (err error) {
|
|||
if n == len(p) {
|
||||
err = nil
|
||||
} else if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
err = errUnexpectedEOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -649,17 +667,17 @@ func (c *Conn) advanceFrame() (int, error) {
|
|||
}
|
||||
case CloseMessage:
|
||||
c.WriteControl(CloseMessage, []byte{}, time.Now().Add(writeWait))
|
||||
if len(payload) < 2 {
|
||||
return noFrame, io.EOF
|
||||
closeCode := CloseNoStatusReceived
|
||||
closeText := ""
|
||||
if len(payload) >= 2 {
|
||||
closeCode = int(binary.BigEndian.Uint16(payload))
|
||||
closeText = string(payload[2:])
|
||||
}
|
||||
closeCode := binary.BigEndian.Uint16(payload)
|
||||
switch closeCode {
|
||||
case CloseNormalClosure, CloseGoingAway:
|
||||
return noFrame, io.EOF
|
||||
default:
|
||||
return noFrame, errors.New("websocket: close " +
|
||||
strconv.Itoa(int(closeCode)) + " " +
|
||||
string(payload[2:]))
|
||||
return noFrame, &closeError{code: closeCode, text: closeText}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -739,7 +757,7 @@ func (r messageReader) Read(b []byte) (int, error) {
|
|||
|
||||
err := r.c.readErr
|
||||
if err == io.EOF && r.seq == r.c.readSeq {
|
||||
err = io.ErrUnexpectedEOF
|
||||
err = errUnexpectedEOF
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
|
14
conn_test.go
14
conn_test.go
|
@ -152,7 +152,7 @@ func TestCloseBeforeFinalFrame(t *testing.T) {
|
|||
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
w.Write(make([]byte, bufSize+bufSize/2))
|
||||
wc.WriteControl(CloseMessage, []byte{}, time.Now().Add(10*time.Second))
|
||||
wc.WriteControl(CloseMessage, FormatCloseMessage(CloseNormalClosure, ""), time.Now().Add(10*time.Second))
|
||||
w.Close()
|
||||
|
||||
op, r, err := rc.NextReader()
|
||||
|
@ -160,8 +160,8 @@ func TestCloseBeforeFinalFrame(t *testing.T) {
|
|||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
_, err = io.Copy(ioutil.Discard, r)
|
||||
if err != io.ErrUnexpectedEOF {
|
||||
t.Fatalf("io.Copy() returned %v, want %v", err, io.ErrUnexpectedEOF)
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("io.Copy() returned %v, want %v", err, errUnexpectedEOF)
|
||||
}
|
||||
_, _, err = rc.NextReader()
|
||||
if err != io.EOF {
|
||||
|
@ -184,12 +184,12 @@ func TestEOFBeforeFinalFrame(t *testing.T) {
|
|||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
_, err = io.Copy(ioutil.Discard, r)
|
||||
if err != io.ErrUnexpectedEOF {
|
||||
t.Fatalf("io.Copy() returned %v, want %v", err, io.ErrUnexpectedEOF)
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("io.Copy() returned %v, want %v", err, errUnexpectedEOF)
|
||||
}
|
||||
_, _, err = rc.NextReader()
|
||||
if err != io.ErrUnexpectedEOF {
|
||||
t.Fatalf("NextReader() returned %v, want %v", err, io.ErrUnexpectedEOF)
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("NextReader() returned %v, want %v", err, errUnexpectedEOF)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
36
doc.go
36
doc.go
|
@ -97,10 +97,13 @@
|
|||
//
|
||||
// Concurrency
|
||||
//
|
||||
// A Conn supports a single concurrent caller to the write methods (NextWriter,
|
||||
// SetWriteDeadline, WriteMessage) and a single concurrent caller to the read
|
||||
// methods (NextReader, SetReadDeadline, ReadMessage). The Close and
|
||||
// WriteControl methods can be called concurrently with all other methods.
|
||||
// Connections do not support concurrent calls to the write methods
|
||||
// (NextWriter, SetWriteDeadline, WriteMessage) or concurrent calls to the read
|
||||
// methods methods (NextReader, SetReadDeadline, ReadMessage). Connections do
|
||||
// support a concurrent reader and writer.
|
||||
//
|
||||
// The Close and WriteControl methods can be called concurrently with all other
|
||||
// methods.
|
||||
//
|
||||
// Read is Required
|
||||
//
|
||||
|
@ -117,4 +120,29 @@
|
|||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Origin Considerations
|
||||
//
|
||||
// Web browsers allow Javascript applications to open a WebSocket connection to
|
||||
// any host. It's up to the server to enforce an origin policy using the Origin
|
||||
// request header sent by the browser.
|
||||
//
|
||||
// The Upgrader calls the function specified in the CheckOrigin field to check
|
||||
// the origin. If the CheckOrigin function returns false, then the Upgrade
|
||||
// method fails the WebSocket handshake with HTTP status 403.
|
||||
//
|
||||
// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail
|
||||
// the handshake if the Origin request header is present and not equal to the
|
||||
// Host request header.
|
||||
//
|
||||
// An application can allow connections from any origin by specifying a
|
||||
// function that always returns true:
|
||||
//
|
||||
// var upgrader = websocket.Upgrader{
|
||||
// CheckOrigin: func(r *http.Request) bool { return true },
|
||||
// }
|
||||
//
|
||||
// The deprecated Upgrade function does not enforce an origin policy. It's the
|
||||
// application's responsibility to check the Origin header before calling
|
||||
// Upgrade.
|
||||
package websocket
|
||||
|
|
15
server.go
15
server.go
|
@ -21,11 +21,6 @@ type HandshakeError struct {
|
|||
|
||||
func (e HandshakeError) Error() string { return e.message }
|
||||
|
||||
const (
|
||||
defaultReadBufferSize = 4096
|
||||
defaultWriteBufferSize = 4096
|
||||
)
|
||||
|
||||
// Upgrader specifies parameters for upgrading an HTTP connection to a
|
||||
// WebSocket connection.
|
||||
type Upgrader struct {
|
||||
|
@ -147,15 +142,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
|||
return nil, errors.New("websocket: client sent data before handshake is complete")
|
||||
}
|
||||
|
||||
readBufSize := u.ReadBufferSize
|
||||
if readBufSize == 0 {
|
||||
readBufSize = defaultReadBufferSize
|
||||
}
|
||||
writeBufSize := u.WriteBufferSize
|
||||
if writeBufSize == 0 {
|
||||
writeBufSize = defaultWriteBufferSize
|
||||
}
|
||||
c := newConn(netConn, true, readBufSize, writeBufSize)
|
||||
c := newConn(netConn, true, u.ReadBufferSize, u.WriteBufferSize)
|
||||
c.subprotocol = subprotocol
|
||||
|
||||
p := c.writeBuf[:0]
|
||||
|
|
Loading…
Reference in New Issue