diff --git a/api/server/server.go b/api/server/server.go index f5c73d1a25..46210cc7f4 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -14,8 +14,8 @@ import ( "strings" "time" - "code.google.com/p/go.net/websocket" "github.com/gorilla/mux" + "golang.org/x/net/websocket" "github.com/Sirupsen/logrus" "github.com/docker/docker/api" diff --git a/hack/.vendor-helpers.sh b/hack/.vendor-helpers.sh index 5846c01ecb..1d4674b247 100755 --- a/hack/.vendor-helpers.sh +++ b/hack/.vendor-helpers.sh @@ -12,8 +12,9 @@ clone() { local vcs="$1" local pkg="$2" local rev="$3" + local url="$4" - local url="https://$pkg" + : ${url:=https://$pkg} local target="vendor/src/$pkg" echo -n "$pkg @ $rev: " diff --git a/hack/vendor.sh b/hack/vendor.sh index 9c0a7c2f07..182f76c2be 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -2,6 +2,7 @@ set -e cd "$(dirname "$BASH_SOURCE")/.." +rm -rf vendor/ source 'hack/.vendor-helpers.sh' # the following lines are in sorted order, FYI @@ -13,7 +14,7 @@ clone git github.com/gorilla/mux e444e69cbd clone git github.com/kr/pty 5cf931ef8f clone git github.com/mistifyio/go-zfs v2.1.1 clone git github.com/tchap/go-patricia v2.1.0 -clone hg code.google.com/p/go.net 84a4013f96e0 +clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git clone hg code.google.com/p/gosqlite 74691fb6f837 #get libnetwork packages diff --git a/integration-cli/docker_api_attach_test.go b/integration-cli/docker_api_attach_test.go index c784d5c369..32e4f7f970 100644 --- a/integration-cli/docker_api_attach_test.go +++ b/integration-cli/docker_api_attach_test.go @@ -7,8 +7,7 @@ import ( "time" "github.com/go-check/check" - - "code.google.com/p/go.net/websocket" + "golang.org/x/net/websocket" ) func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) { diff --git a/vendor/src/code.google.com/p/go.net/websocket/hixie.go b/vendor/src/code.google.com/p/go.net/websocket/hixie.go deleted file mode 100644 index 80bd524950..0000000000 --- a/vendor/src/code.google.com/p/go.net/websocket/hixie.go +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package websocket - -// This file implements a protocol of Hixie draft version 75 and 76 -// (draft 76 equals to hybi 00) - -import ( - "bufio" - "bytes" - "crypto/md5" - "encoding/binary" - "fmt" - "io" - "io/ioutil" - "math/rand" - "net/http" - "net/url" - "strconv" - "strings" -) - -// An array of characters to be randomly inserted to construct Sec-WebSocket-Key -// value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E. -// See Step 21 in Section 4.1 Opening handshake. -// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22 -var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte - -func init() { - i := 0 - for ch := byte(0x21); ch < 0x30; ch++ { - secKeyRandomChars[i] = ch - i++ - } - for ch := byte(0x3a); ch < 0x7F; ch++ { - secKeyRandomChars[i] = ch - i++ - } -} - -type byteReader interface { - ReadByte() (byte, error) -} - -// readHixieLength reads frame length for frame type 0x80-0xFF -// as defined in Hixie draft. -// See section 4.2 Data framing. -// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2 -func readHixieLength(r byteReader) (length int64, lengthFields []byte, err error) { - for { - c, err := r.ReadByte() - if err != nil { - return 0, nil, err - } - lengthFields = append(lengthFields, c) - length = length*128 + int64(c&0x7f) - if c&0x80 == 0 { - break - } - } - return -} - -// A hixieLengthFrameReader is a reader for frame type 0x80-0xFF -// as defined in hixie draft. -type hixieLengthFrameReader struct { - reader io.Reader - FrameType byte - Length int64 - header *bytes.Buffer - length int -} - -func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err error) { - return frame.reader.Read(msg) -} - -func (frame *hixieLengthFrameReader) PayloadType() byte { - if frame.FrameType == '\xff' && frame.Length == 0 { - return CloseFrame - } - return UnknownFrame -} - -func (frame *hixieLengthFrameReader) HeaderReader() io.Reader { - if frame.header == nil { - return nil - } - if frame.header.Len() == 0 { - frame.header = nil - return nil - } - return frame.header -} - -func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil } - -func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length } - -// A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F -// as defined in hixie draft. -type hixieSentinelFrameReader struct { - reader *bufio.Reader - FrameType byte - header *bytes.Buffer - data []byte - seenTrailer bool - trailer *bytes.Buffer -} - -func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err error) { - if len(frame.data) == 0 { - if frame.seenTrailer { - return 0, io.EOF - } - frame.data, err = frame.reader.ReadSlice('\xff') - if err == nil { - frame.seenTrailer = true - frame.data = frame.data[:len(frame.data)-1] // trim \xff - frame.trailer = bytes.NewBuffer([]byte{0xff}) - } - } - n = copy(msg, frame.data) - frame.data = frame.data[n:] - return n, err -} - -func (frame *hixieSentinelFrameReader) PayloadType() byte { - if frame.FrameType == 0 { - return TextFrame - } - return UnknownFrame -} - -func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader { - if frame.header == nil { - return nil - } - if frame.header.Len() == 0 { - frame.header = nil - return nil - } - return frame.header -} - -func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader { - if frame.trailer == nil { - return nil - } - if frame.trailer.Len() == 0 { - frame.trailer = nil - return nil - } - return frame.trailer -} - -func (frame *hixieSentinelFrameReader) Len() int { return -1 } - -// A HixieFrameReaderFactory creates new frame reader based on its frame type. -type hixieFrameReaderFactory struct { - *bufio.Reader -} - -func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err error) { - var header []byte - var b byte - b, err = buf.ReadByte() - if err != nil { - return - } - header = append(header, b) - if b&0x80 == 0x80 { - length, lengthFields, err := readHixieLength(buf.Reader) - if err != nil { - return nil, err - } - if length == 0 { - return nil, io.EOF - } - header = append(header, lengthFields...) - return &hixieLengthFrameReader{ - reader: io.LimitReader(buf.Reader, length), - FrameType: b, - Length: length, - header: bytes.NewBuffer(header)}, err - } - return &hixieSentinelFrameReader{ - reader: buf.Reader, - FrameType: b, - header: bytes.NewBuffer(header)}, err -} - -type hixiFrameWriter struct { - writer *bufio.Writer -} - -func (frame *hixiFrameWriter) Write(msg []byte) (n int, err error) { - frame.writer.WriteByte(0) - frame.writer.Write(msg) - frame.writer.WriteByte(0xff) - err = frame.writer.Flush() - return len(msg), err -} - -func (frame *hixiFrameWriter) Close() error { return nil } - -type hixiFrameWriterFactory struct { - *bufio.Writer -} - -func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err error) { - if payloadType != TextFrame { - return nil, ErrNotSupported - } - return &hixiFrameWriter{writer: buf.Writer}, nil -} - -type hixiFrameHandler struct { - conn *Conn -} - -func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err error) { - if header := frame.HeaderReader(); header != nil { - io.Copy(ioutil.Discard, header) - } - if frame.PayloadType() != TextFrame { - io.Copy(ioutil.Discard, frame) - return nil, nil - } - return frame, nil -} - -func (handler *hixiFrameHandler) WriteClose(_ int) (err error) { - handler.conn.wio.Lock() - defer handler.conn.wio.Unlock() - closingFrame := []byte{'\xff', '\x00'} - handler.conn.buf.Write(closingFrame) - return handler.conn.buf.Flush() -} - -// newHixiConn creates a new WebSocket connection speaking hixie draft protocol. -func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn { - if buf == nil { - br := bufio.NewReader(rwc) - bw := bufio.NewWriter(rwc) - buf = bufio.NewReadWriter(br, bw) - } - ws := &Conn{config: config, request: request, buf: buf, rwc: rwc, - frameReaderFactory: hixieFrameReaderFactory{buf.Reader}, - frameWriterFactory: hixiFrameWriterFactory{buf.Writer}, - PayloadType: TextFrame} - ws.frameHandler = &hixiFrameHandler{ws} - return ws -} - -// getChallengeResponse computes the expected response from the -// challenge as described in section 5.1 Opening Handshake steps 42 to -// 43 of http://www.whatwg.org/specs/web-socket-protocol/ -func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err error) { - // 41. Let /challenge/ be the concatenation of /number_1/, expressed - // a big-endian 32 bit integer, /number_2/, expressed in a big- - // endian 32 bit integer, and the eight bytes of /key_3/ in the - // order they were sent to the wire. - challenge := make([]byte, 16) - binary.BigEndian.PutUint32(challenge[0:], number1) - binary.BigEndian.PutUint32(challenge[4:], number2) - copy(challenge[8:], key3) - - // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big- - // endian 128 bit string. - h := md5.New() - if _, err = h.Write(challenge); err != nil { - return - } - expected = h.Sum(nil) - return -} - -// Generates handshake key as described in 4.1 Opening handshake step 16 to 22. -// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00 -func generateKeyNumber() (key string, number uint32) { - // 16. Let /spaces_n/ be a random integer from 1 to 12 inclusive. - spaces := rand.Intn(12) + 1 - - // 17. Let /max_n/ be the largest integer not greater than - // 4,294,967,295 divided by /spaces_n/ - max := int(4294967295 / uint32(spaces)) - - // 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive. - number = uint32(rand.Intn(max + 1)) - - // 19. Let /product_n/ be the result of multiplying /number_n/ and - // /spaces_n/ together. - product := number * uint32(spaces) - - // 20. Let /key_n/ be a string consisting of /product_n/, expressed - // in base ten using the numerals in the range U+0030 DIGIT ZERO (0) - // to U+0039 DIGIT NINE (9). - key = fmt.Sprintf("%d", product) - - // 21. Insert between one and twelve random characters from the ranges - // U+0021 to U+002F and U+003A to U+007E into /key_n/ at random - // positions. - n := rand.Intn(12) + 1 - for i := 0; i < n; i++ { - pos := rand.Intn(len(key)) + 1 - ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))] - key = key[0:pos] + string(ch) + key[pos:] - } - - // 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random - // positions other than the start or end of the string. - for i := 0; i < spaces; i++ { - pos := rand.Intn(len(key)-1) + 1 - key = key[0:pos] + " " + key[pos:] - } - - return -} - -// Generates handshake key_3 as described in 4.1 Opening handshake step 26. -// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00 -func generateKey3() (key []byte) { - // 26. Let /key3/ be a string consisting of eight random bytes (or - // equivalently, a random 64 bit integer encoded in big-endian order). - key = make([]byte, 8) - for i := 0; i < 8; i++ { - key[i] = byte(rand.Intn(256)) - } - return -} - -// Client handshake described in (soon obsolete) -// draft-ietf-hybi-thewebsocket-protocol-00 -// (draft-hixie-thewebsocket-protocol-76) -func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) { - switch config.Version { - case ProtocolVersionHixie76, ProtocolVersionHybi00: - default: - panic("wrong protocol version.") - } - // 4.1. Opening handshake. - // Step 5. send a request line. - bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n") - - // Step 6-14. push request headers in fields. - fields := []string{ - "Upgrade: WebSocket\r\n", - "Connection: Upgrade\r\n", - "Host: " + config.Location.Host + "\r\n", - "Origin: " + config.Origin.String() + "\r\n", - } - if len(config.Protocol) > 0 { - if len(config.Protocol) != 1 { - return ErrBadWebSocketProtocol - } - fields = append(fields, "Sec-WebSocket-Protocol: "+config.Protocol[0]+"\r\n") - } - // TODO(ukai): Step 15. send cookie if any. - - // Step 16-23. generate keys and push Sec-WebSocket-Key in fields. - key1, number1 := generateKeyNumber() - key2, number2 := generateKeyNumber() - if config.handshakeData != nil { - key1 = config.handshakeData["key1"] - n, err := strconv.ParseUint(config.handshakeData["number1"], 10, 32) - if err != nil { - panic(err) - } - number1 = uint32(n) - key2 = config.handshakeData["key2"] - n, err = strconv.ParseUint(config.handshakeData["number2"], 10, 32) - if err != nil { - panic(err) - } - number2 = uint32(n) - } - fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n") - fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n") - - // Step 24. shuffle fields and send them out. - for i := 1; i < len(fields); i++ { - j := rand.Intn(i) - fields[i], fields[j] = fields[j], fields[i] - } - for i := 0; i < len(fields); i++ { - bw.WriteString(fields[i]) - } - // Step 25. send CRLF. - bw.WriteString("\r\n") - - // Step 26. generate 8 bytes random key. - key3 := generateKey3() - if config.handshakeData != nil { - key3 = []byte(config.handshakeData["key3"]) - } - // Step 27. send it out. - bw.Write(key3) - if err = bw.Flush(); err != nil { - return - } - - // Step 28-29, 32-40. read response from server. - resp, err := http.ReadResponse(br, &http.Request{Method: "GET"}) - if err != nil { - return err - } - // Step 30. check response code is 101. - if resp.StatusCode != 101 { - return ErrBadStatus - } - - // Step 41. check websocket headers. - if resp.Header.Get("Upgrade") != "WebSocket" || - strings.ToLower(resp.Header.Get("Connection")) != "upgrade" { - return ErrBadUpgrade - } - - if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() { - return ErrBadWebSocketOrigin - } - - if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() { - return ErrBadWebSocketLocation - } - - if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] { - return ErrBadWebSocketProtocol - } - - // Step 42-43. get expected data from challenge data. - expected, err := getChallengeResponse(number1, number2, key3) - if err != nil { - return err - } - - // Step 44. read 16 bytes from server. - reply := make([]byte, 16) - if _, err = io.ReadFull(br, reply); err != nil { - return err - } - - // Step 45. check the reply equals to expected data. - if !bytes.Equal(expected, reply) { - return ErrChallengeResponse - } - // WebSocket connection is established. - return -} - -// Client Handshake described in (soon obsolete) -// draft-hixie-thewebsocket-protocol-75. -func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err error) { - if config.Version != ProtocolVersionHixie75 { - panic("wrong protocol version.") - } - bw.WriteString("GET " + config.Location.RequestURI() + " HTTP/1.1\r\n") - bw.WriteString("Upgrade: WebSocket\r\n") - bw.WriteString("Connection: Upgrade\r\n") - bw.WriteString("Host: " + config.Location.Host + "\r\n") - bw.WriteString("Origin: " + config.Origin.String() + "\r\n") - if len(config.Protocol) > 0 { - if len(config.Protocol) != 1 { - return ErrBadWebSocketProtocol - } - bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n") - } - bw.WriteString("\r\n") - bw.Flush() - resp, err := http.ReadResponse(br, &http.Request{Method: "GET"}) - if err != nil { - return - } - if resp.Status != "101 Web Socket Protocol Handshake" { - return ErrBadStatus - } - if resp.Header.Get("Upgrade") != "WebSocket" || - resp.Header.Get("Connection") != "Upgrade" { - return ErrBadUpgrade - } - if resp.Header.Get("Websocket-Origin") != config.Origin.String() { - return ErrBadWebSocketOrigin - } - if resp.Header.Get("Websocket-Location") != config.Location.String() { - return ErrBadWebSocketLocation - } - if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] { - return ErrBadWebSocketProtocol - } - return -} - -// newHixieClientConn returns new WebSocket connection speaking hixie draft protocol. -func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn { - return newHixieConn(config, buf, rwc, nil) -} - -// Gets key number from Sec-WebSocket-Key: field as described -// in 5.2 Sending the server's opening handshake, 4. -func getKeyNumber(s string) (r uint32) { - // 4. Let /key-number_n/ be the digits (characters in the range - // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/, - // interpreted as a base ten integer, ignoring all other characters - // in /key_n/. - r = 0 - for i := 0; i < len(s); i++ { - if s[i] >= '0' && s[i] <= '9' { - r = r*10 + uint32(s[i]) - '0' - } - } - return -} - -// A Hixie76ServerHandshaker performs a server handshake using -// hixie draft 76 protocol. -type hixie76ServerHandshaker struct { - *Config - challengeResponse []byte -} - -func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) { - c.Version = ProtocolVersionHybi00 - if req.Method != "GET" { - return http.StatusMethodNotAllowed, ErrBadRequestMethod - } - // HTTP version can be safely ignored. - - if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" || - strings.ToLower(req.Header.Get("Connection")) != "upgrade" { - return http.StatusBadRequest, ErrNotWebSocket - } - - // TODO(ukai): check Host - c.Origin, err = url.ParseRequestURI(req.Header.Get("Origin")) - if err != nil { - return http.StatusBadRequest, err - } - - key1 := req.Header.Get("Sec-Websocket-Key1") - if key1 == "" { - return http.StatusBadRequest, ErrChallengeResponse - } - key2 := req.Header.Get("Sec-Websocket-Key2") - if key2 == "" { - return http.StatusBadRequest, ErrChallengeResponse - } - key3 := make([]byte, 8) - if _, err := io.ReadFull(buf, key3); err != nil { - return http.StatusBadRequest, ErrChallengeResponse - } - - var scheme string - if req.TLS != nil { - scheme = "wss" - } else { - scheme = "ws" - } - c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI()) - if err != nil { - return http.StatusBadRequest, err - } - - // Step 4. get key number in Sec-WebSocket-Key fields. - keyNumber1 := getKeyNumber(key1) - keyNumber2 := getKeyNumber(key2) - - // Step 5. get number of spaces in Sec-WebSocket-Key fields. - space1 := uint32(strings.Count(key1, " ")) - space2 := uint32(strings.Count(key2, " ")) - if space1 == 0 || space2 == 0 { - return http.StatusBadRequest, ErrChallengeResponse - } - - // Step 6. key number must be an integral multiple of spaces. - if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 { - return http.StatusBadRequest, ErrChallengeResponse - } - - // Step 7. let part be key number divided by spaces. - part1 := keyNumber1 / space1 - part2 := keyNumber2 / space2 - - // Step 8. let challenge be concatenation of part1, part2 and key3. - // Step 9. get MD5 fingerprint of challenge. - c.challengeResponse, err = getChallengeResponse(part1, part2, key3) - if err != nil { - return http.StatusInternalServerError, err - } - protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol")) - protocols := strings.Split(protocol, ",") - for i := 0; i < len(protocols); i++ { - c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i])) - } - - return http.StatusSwitchingProtocols, nil -} - -func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) { - if len(c.Protocol) > 0 { - if len(c.Protocol) != 1 { - return ErrBadWebSocketProtocol - } - } - - // Step 10. send response status line. - buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n") - // Step 11. send response headers. - buf.WriteString("Upgrade: WebSocket\r\n") - buf.WriteString("Connection: Upgrade\r\n") - buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n") - buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n") - if len(c.Protocol) > 0 { - buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n") - } - // Step 12. send CRLF. - buf.WriteString("\r\n") - // Step 13. send response data. - buf.Write(c.challengeResponse) - return buf.Flush() -} - -func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) { - return newHixieServerConn(c.Config, buf, rwc, request) -} - -// A hixie75ServerHandshaker performs a server handshake using -// hixie draft 75 protocol. -type hixie75ServerHandshaker struct { - *Config -} - -func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) { - c.Version = ProtocolVersionHixie75 - if req.Method != "GET" || req.Proto != "HTTP/1.1" { - return http.StatusMethodNotAllowed, ErrBadRequestMethod - } - if req.Header.Get("Upgrade") != "WebSocket" { - return http.StatusBadRequest, ErrNotWebSocket - } - if req.Header.Get("Connection") != "Upgrade" { - return http.StatusBadRequest, ErrNotWebSocket - } - c.Origin, err = url.ParseRequestURI(strings.TrimSpace(req.Header.Get("Origin"))) - if err != nil { - return http.StatusBadRequest, err - } - - var scheme string - if req.TLS != nil { - scheme = "wss" - } else { - scheme = "ws" - } - c.Location, err = url.ParseRequestURI(scheme + "://" + req.Host + req.URL.RequestURI()) - if err != nil { - return http.StatusBadRequest, err - } - protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol")) - protocols := strings.Split(protocol, ",") - for i := 0; i < len(protocols); i++ { - c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i])) - } - - return http.StatusSwitchingProtocols, nil -} - -func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err error) { - if len(c.Protocol) > 0 { - if len(c.Protocol) != 1 { - return ErrBadWebSocketProtocol - } - } - - buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n") - buf.WriteString("Upgrade: WebSocket\r\n") - buf.WriteString("Connection: Upgrade\r\n") - buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n") - buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n") - if len(c.Protocol) > 0 { - buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n") - } - buf.WriteString("\r\n") - return buf.Flush() -} - -func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) { - return newHixieServerConn(c.Config, buf, rwc, request) -} - -// newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol. -func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn { - return newHixieConn(config, buf, rwc, request) -} diff --git a/vendor/src/code.google.com/p/go.net/websocket/client.go b/vendor/src/golang.org/x/net/websocket/client.go similarity index 74% rename from vendor/src/code.google.com/p/go.net/websocket/client.go rename to vendor/src/golang.org/x/net/websocket/client.go index df54a68810..20d1e1e38e 100644 --- a/vendor/src/code.google.com/p/go.net/websocket/client.go +++ b/vendor/src/golang.org/x/net/websocket/client.go @@ -43,26 +43,12 @@ func NewConfig(server, origin string) (config *Config, err error) { func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) { br := bufio.NewReader(rwc) bw := bufio.NewWriter(rwc) - switch config.Version { - 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 - } + err = hybiClientHandshake(config, br, bw) if err != nil { return } buf := bufio.NewReadWriter(br, bw) - switch config.Version { - case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00: - ws = newHixieClientConn(config, buf, rwc) - case ProtocolVersionHybi08, ProtocolVersionHybi13: - ws = newHybiClientConn(config, buf, rwc) - } + ws = newHybiClientConn(config, buf, rwc) return } @@ -78,6 +64,20 @@ func Dial(url_, protocol, origin string) (ws *Conn, err error) { return DialConfig(config) } +var portMap = map[string]string{ + "ws": "80", + "wss": "443", +} + +func parseAuthority(location *url.URL) string { + if _, ok := portMap[location.Scheme]; ok { + if _, _, err := net.SplitHostPort(location.Host); err != nil { + return net.JoinHostPort(location.Host, portMap[location.Scheme]) + } + } + return location.Host +} + // DialConfig opens a new client connection to a WebSocket with a config. func DialConfig(config *Config) (ws *Conn, err error) { var client net.Conn @@ -89,10 +89,10 @@ func DialConfig(config *Config) (ws *Conn, err error) { } switch config.Location.Scheme { case "ws": - client, err = net.Dial("tcp", config.Location.Host) + client, err = net.Dial("tcp", parseAuthority(config.Location)) case "wss": - client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig) + client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig) default: err = ErrBadScheme @@ -103,6 +103,7 @@ func DialConfig(config *Config) (ws *Conn, err error) { ws, err = NewClient(config, client) if err != nil { + client.Close() goto Error } return diff --git a/vendor/src/code.google.com/p/go.net/websocket/hybi.go b/vendor/src/golang.org/x/net/websocket/hybi.go similarity index 96% rename from vendor/src/code.google.com/p/go.net/websocket/hybi.go rename to vendor/src/golang.org/x/net/websocket/hybi.go index 90f5d9ca01..f8c0b2e299 100644 --- a/vendor/src/code.google.com/p/go.net/websocket/hybi.go +++ b/vendor/src/golang.org/x/net/websocket/hybi.go @@ -385,21 +385,8 @@ func getNonceAccept(nonce []byte) (expected []byte, err error) { 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 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("Host: " + config.Location.Host + "\r\n") @@ -410,11 +397,12 @@ func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (er nonce = []byte(config.handshakeData["key"]) } bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n") - if config.Version == ProtocolVersionHybi13 { - bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") - } else if config.Version == ProtocolVersionHybi08 { - bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") + bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n") + + if config.Version != ProtocolVersionHybi13 { + return ErrBadProtocolVersion } + bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n") if len(config.Protocol) > 0 { 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 switch version { case "13": c.Version = ProtocolVersionHybi13 - case "8": - c.Version = ProtocolVersionHybi08 default: return http.StatusBadRequest, ErrBadWebSocketVersion } @@ -536,8 +522,6 @@ func Origin(config *Config, req *http.Request) (*url.URL, error) { switch config.Version { case ProtocolVersionHybi13: origin = req.Header.Get("Origin") - case ProtocolVersionHybi08: - origin = req.Header.Get("Sec-Websocket-Origin") } if origin == "null" { return nil, nil diff --git a/vendor/src/code.google.com/p/go.net/websocket/server.go b/vendor/src/golang.org/x/net/websocket/server.go similarity index 90% rename from vendor/src/code.google.com/p/go.net/websocket/server.go rename to vendor/src/golang.org/x/net/websocket/server.go index 54e05b4300..33f99b1e5e 100644 --- a/vendor/src/code.google.com/p/go.net/websocket/server.go +++ b/vendor/src/golang.org/x/net/websocket/server.go @@ -22,14 +22,6 @@ func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Requ buf.Flush() 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 { fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) buf.WriteString("\r\n") @@ -103,8 +95,8 @@ func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) { // You might want to verify websocket.Conn.Config().Origin in the func. // If you use Server instead of Handler, you could call websocket.Origin and // check the origin in your Handshake func. So, if you want to accept -// non-browser client, which doesn't send Origin header, you could use Server -//. that doesn't check origin in its Handshake. +// non-browser clients, which do not send an Origin header, set a +// Server.Handshake that does not check the origin. type Handler func(*Conn) func checkOrigin(config *Config, req *http.Request) (err error) { diff --git a/vendor/src/code.google.com/p/go.net/websocket/websocket.go b/vendor/src/golang.org/x/net/websocket/websocket.go similarity index 97% rename from vendor/src/code.google.com/p/go.net/websocket/websocket.go rename to vendor/src/golang.org/x/net/websocket/websocket.go index 861b3c68f2..6068400980 100644 --- a/vendor/src/code.google.com/p/go.net/websocket/websocket.go +++ b/vendor/src/golang.org/x/net/websocket/websocket.go @@ -4,7 +4,7 @@ // Package websocket implements a client and server for the WebSocket protocol // as specified in RFC 6455. -package websocket +package websocket // import "golang.org/x/net/websocket" import ( "bufio" @@ -21,13 +21,9 @@ import ( ) const ( - ProtocolVersionHixie75 = -75 - ProtocolVersionHixie76 = -76 - ProtocolVersionHybi00 = 0 - ProtocolVersionHybi08 = 8 ProtocolVersionHybi13 = 13 ProtocolVersionHybi = ProtocolVersionHybi13 - SupportedProtocolVersion = "13, 8" + SupportedProtocolVersion = "13" ContinuationFrame = 0 TextFrame = 1 @@ -133,7 +129,7 @@ type frameReaderFactory interface { // frameWriter is an interface to write a WebSocket frame. type frameWriter interface { - // Writer is to write playload of the frame. + // Writer is to write payload of the frame. io.WriteCloser } @@ -220,10 +216,11 @@ func (ws *Conn) Write(msg []byte) (n int, err error) { // Close implements the io.Closer interface. func (ws *Conn) Close() error { err := ws.frameHandler.WriteClose(ws.defaultCloseStatus) + err1 := ws.rwc.Close() if err != nil { return err } - return ws.rwc.Close() + return err1 } func (ws *Conn) IsClientConn() bool { return ws.request == nil }