Commit 38c17adf authored by Scott Ferguson's avatar Scott Ferguson Committed by Andrew Gerrand

go.net/websocket: drop old versions of the protocol

Most modern web browsers support RFC6455, so it's okay to drop older versions.
Fixes golang/go#5628.

R=golang-dev, ukai
CC=golang-dev
https://golang.org/cl/10480043
parent ee2e27e1
...@@ -43,26 +43,12 @@ func NewConfig(server, origin string) (config *Config, err error) { ...@@ -43,26 +43,12 @@ func NewConfig(server, origin string) (config *Config, err error) {
func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) { func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
br := bufio.NewReader(rwc) br := bufio.NewReader(rwc)
bw := bufio.NewWriter(rwc) bw := bufio.NewWriter(rwc)
switch config.Version { err = hybiClientHandshake(config, br, bw)
case ProtocolVersionHixie75:
err = hixie75ClientHandshake(config, br, bw)
case ProtocolVersionHixie76, ProtocolVersionHybi00:
err = hixie76ClientHandshake(config, br, bw)
case ProtocolVersionHybi08, ProtocolVersionHybi13:
err = hybiClientHandshake(config, br, bw)
default:
err = ErrBadProtocolVersion
}
if err != nil { if err != nil {
return return
} }
buf := bufio.NewReadWriter(br, bw) buf := bufio.NewReadWriter(br, bw)
switch config.Version { ws = newHybiClientConn(config, buf, rwc)
case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00:
ws = newHixieClientConn(config, buf, rwc)
case ProtocolVersionHybi08, ProtocolVersionHybi13:
ws = newHybiClientConn(config, buf, rwc)
}
return return
} }
......
...@@ -385,21 +385,8 @@ func getNonceAccept(nonce []byte) (expected []byte, err error) { ...@@ -385,21 +385,8 @@ func getNonceAccept(nonce []byte) (expected []byte, err error) {
return return
} }
func isHybiVersion(version int) bool {
switch version {
case ProtocolVersionHybi08, ProtocolVersionHybi13:
return true
default:
}
return false
}
// Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17 // Client handshake described in draft-ietf-hybi-thewebsocket-protocol-17
func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) { func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) {
if !isHybiVersion(config.Version) {
panic("wrong protocol version.")
}
bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n") bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n")
bw.WriteString("Host: " + config.Location.Host + "\r\n") bw.WriteString("Host: " + config.Location.Host + "\r\n")
...@@ -410,11 +397,12 @@ func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (er ...@@ -410,11 +397,12 @@ func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (er
nonce = []byte(config.handshakeData["key"]) nonce = []byte(config.handshakeData["key"])
} }
bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n") bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
if config.Version == ProtocolVersionHybi13 { bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
} else if config.Version == ProtocolVersionHybi08 { if config.Version != ProtocolVersionHybi13 {
bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") return ErrBadProtocolVersion
} }
bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n") bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
if len(config.Protocol) > 0 { if len(config.Protocol) > 0 {
bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n") bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
...@@ -500,8 +488,6 @@ func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Reques ...@@ -500,8 +488,6 @@ func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Reques
switch version { switch version {
case "13": case "13":
c.Version = ProtocolVersionHybi13 c.Version = ProtocolVersionHybi13
case "8":
c.Version = ProtocolVersionHybi08
default: default:
return http.StatusBadRequest, ErrBadWebSocketVersion return http.StatusBadRequest, ErrBadWebSocketVersion
} }
...@@ -536,8 +522,6 @@ func Origin(config *Config, req *http.Request) (*url.URL, error) { ...@@ -536,8 +522,6 @@ func Origin(config *Config, req *http.Request) (*url.URL, error) {
switch config.Version { switch config.Version {
case ProtocolVersionHybi13: case ProtocolVersionHybi13:
origin = req.Header.Get("Origin") origin = req.Header.Get("Origin")
case ProtocolVersionHybi08:
origin = req.Header.Get("Sec-Websocket-Origin")
} }
if origin == "null" { if origin == "null" {
return nil, nil return nil, nil
......
...@@ -157,68 +157,6 @@ Sec-WebSocket-Protocol: chat ...@@ -157,68 +157,6 @@ Sec-WebSocket-Protocol: chat
} }
} }
func TestHybiClientHandshakeHybi08(t *testing.T) {
b := bytes.NewBuffer([]byte{})
bw := bufio.NewWriter(b)
br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
`))
var err error
config := new(Config)
config.Location, err = url.ParseRequestURI("ws://server.example.com/chat")
if err != nil {
t.Fatal("location url", err)
}
config.Origin, err = url.ParseRequestURI("http://example.com")
if err != nil {
t.Fatal("origin url", err)
}
config.Protocol = append(config.Protocol, "chat")
config.Protocol = append(config.Protocol, "superchat")
config.Version = ProtocolVersionHybi08
config.handshakeData = map[string]string{
"key": "dGhlIHNhbXBsZSBub25jZQ==",
}
err = hybiClientHandshake(config, br, bw)
if err != nil {
t.Errorf("handshake failed: %v", err)
}
req, err := http.ReadRequest(bufio.NewReader(b))
if err != nil {
t.Fatalf("read request: %v", err)
}
if req.Method != "GET" {
t.Errorf("request method expected GET, but got %q", req.Method)
}
if req.URL.Path != "/chat" {
t.Errorf("request path expected /demo, but got %q", req.URL.Path)
}
if req.Proto != "HTTP/1.1" {
t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
}
if req.Host != "server.example.com" {
t.Errorf("request Host expected example.com, but got %v", req.Host)
}
var expectedHeader = map[string]string{
"Connection": "Upgrade",
"Upgrade": "websocket",
"Sec-Websocket-Key": config.handshakeData["key"],
"Sec-Websocket-Origin": config.Origin.String(),
"Sec-Websocket-Protocol": "chat, superchat",
"Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi08),
}
for k, v := range expectedHeader {
if req.Header.Get(k) != v {
t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
}
}
}
func TestHybiServerHandshake(t *testing.T) { func TestHybiServerHandshake(t *testing.T) {
config := new(Config) config := new(Config)
handshaker := &hybiServerHandshaker{Config: config} handshaker := &hybiServerHandshaker{Config: config}
...@@ -314,52 +252,6 @@ Sec-WebSocket-Version: 13 ...@@ -314,52 +252,6 @@ Sec-WebSocket-Version: 13
} }
} }
func TestHybiServerHandshakeHybi08(t *testing.T) {
config := new(Config)
handshaker := &hybiServerHandshaker{Config: config}
br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 8
`))
req, err := http.ReadRequest(br)
if err != nil {
t.Fatal("request", err)
}
code, err := handshaker.ReadHandshake(br, req)
if err != nil {
t.Errorf("handshake failed: %v", err)
}
if code != http.StatusSwitchingProtocols {
t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
}
b := bytes.NewBuffer([]byte{})
bw := bufio.NewWriter(b)
config.Protocol = []string{"chat"}
err = handshaker.AcceptHandshake(bw)
if err != nil {
t.Errorf("handshake response failed: %v", err)
}
expectedResponse := strings.Join([]string{
"HTTP/1.1 101 Switching Protocols",
"Upgrade: websocket",
"Connection: Upgrade",
"Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
"Sec-WebSocket-Protocol: chat",
"", ""}, "\r\n")
if b.String() != expectedResponse {
t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
}
}
func TestHybiServerHandshakeHybiBadVersion(t *testing.T) { func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
config := new(Config) config := new(Config)
handshaker := &hybiServerHandshaker{Config: config} handshaker := &hybiServerHandshaker{Config: config}
......
...@@ -22,14 +22,6 @@ func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Requ ...@@ -22,14 +22,6 @@ func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Requ
buf.Flush() buf.Flush()
return return
} }
if err != nil {
hs = &hixie76ServerHandshaker{Config: config}
code, err = hs.ReadHandshake(buf.Reader, req)
}
if err != nil {
hs = &hixie75ServerHandshaker{Config: config}
code, err = hs.ReadHandshake(buf.Reader, req)
}
if err != nil { if err != nil {
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
buf.WriteString("\r\n") buf.WriteString("\r\n")
......
...@@ -21,13 +21,9 @@ import ( ...@@ -21,13 +21,9 @@ import (
) )
const ( const (
ProtocolVersionHixie75 = -75
ProtocolVersionHixie76 = -76
ProtocolVersionHybi00 = 0
ProtocolVersionHybi08 = 8
ProtocolVersionHybi13 = 13 ProtocolVersionHybi13 = 13
ProtocolVersionHybi = ProtocolVersionHybi13 ProtocolVersionHybi = ProtocolVersionHybi13
SupportedProtocolVersion = "13, 8" SupportedProtocolVersion = "13"
ContinuationFrame = 0 ContinuationFrame = 0
TextFrame = 1 TextFrame = 1
......
...@@ -286,6 +286,20 @@ func TestTrailingSpaces(t *testing.T) { ...@@ -286,6 +286,20 @@ func TestTrailingSpaces(t *testing.T) {
} }
} }
func TestDialConfigBadVersion(t *testing.T) {
once.Do(startServer)
config := newConfig(t, "/echo")
config.Version = 1234
_, err := DialConfig(config)
if dialerr, ok := err.(*DialError); ok {
if dialerr.Err != ErrBadProtocolVersion {
t.Errorf("dial expected err %q but got %q", ErrBadProtocolVersion, dialerr.Err)
}
}
}
func TestSmallBuffer(t *testing.T) { func TestSmallBuffer(t *testing.T) {
// http://code.google.com/p/go/issues/detail?id=1145 // http://code.google.com/p/go/issues/detail?id=1145
// Read should be able to handle reading a fragment of a frame. // Read should be able to handle reading a fragment of a frame.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment