// 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"
	"http"
	"io"
	"io/ioutil"
	"os"
	"rand"
	"strconv"
	"strings"
	"url"
)

// An aray 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, os.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 os.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 os.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 os.Error) {
	if len(frame.data) == 0 {
		if frame.seenTrailer {
			return 0, os.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 os.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, os.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 os.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() os.Error { return nil }

type hixiFrameWriterFactory struct {
	*bufio.Writer
}

func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err os.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 os.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 os.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 os.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()
	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
}

// Cilent handhake 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 os.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.RawPath + " 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<n> in fields.
	key1, number1 := generateKeyNumber()
	key2, number2 := generateKeyNumber()
	if config.handshakeData != nil {
		key1 = config.handshakeData["key1"]
		n, err := strconv.Atoui(config.handshakeData["number1"])
		if err != nil {
			panic(err)
		}
		number1 = uint32(n)
		key2 = config.handshakeData["key2"]
		n, err = strconv.Atoui(config.handshakeData["number2"])
		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 os.Error) {
	if config.Version != ProtocolVersionHixie75 {
		panic("wrong protocol version.")
	}
	bw.WriteString("GET " + config.Location.RawPath + " 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<n>: 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 os.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.ParseRequest(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.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
	if err != nil {
		return http.StatusBadRequest, err
	}

	// Step 4. get key number in Sec-WebSocket-Key<n> fields.
	keyNumber1 := getKeyNumber(key1)
	keyNumber2 := getKeyNumber(key2)

	// Step 5. get number of spaces in Sec-WebSocket-Key<n> 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 os.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 os.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.ParseRequest(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.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
	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 os.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)
}
