// 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

import (
	"bufio"
	"bytes"
	"container/vector"
	"fmt"
	"http"
	"io"
	"net"
	"os"
	"rand"
	"strings"
)

type ProtocolError struct {
	os.ErrorString
}

var (
	ErrBadStatus            = &ProtocolError{"bad status"}
	ErrBadUpgrade           = &ProtocolError{"missing or bad upgrade"}
	ErrBadWebSocketOrigin   = &ProtocolError{"missing or bad WebSocket-Origin"}
	ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
	ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
	ErrChallengeResponse    = &ProtocolError{"mismatch challange/response"}
	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 handshaker func(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) os.Error

// newClient creates a new Web Socket client connection.
func newClient(resourceName, host, origin, location, protocol string, rwc io.ReadWriteCloser, handshake handshaker) (ws *Conn, err os.Error) {
	br := bufio.NewReader(rwc)
	bw := bufio.NewWriter(rwc)
	err = handshake(resourceName, host, origin, location, protocol, br, bw)
	if err != nil {
		return
	}
	buf := bufio.NewReadWriter(br, bw)
	ws = newConn(origin, location, protocol, buf, rwc)
	return
}

/*
Dial opens a new client connection to a Web Socket.

A trivial example client:

	package main

	import (
		"websocket"
		"strings"
	)

	func main() {
	 	ws, err := websocket.Dial("ws://localhost/ws", "", "http://localhost/");
	 	if err != nil {
			panic("Dial: " + err.String())
		}
		if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
			panic("Write: " + err.String())
		}
		var msg = make([]byte, 512);
		if n, err := ws.Read(msg); err != nil {
			panic("Read: " + err.String())
		}
		// use msg[0:n]
	}
*/
func Dial(url, protocol, origin string) (ws *Conn, err os.Error) {
	parsedUrl, err := http.ParseURL(url)
	if err != nil {
		return
	}
	client, err := net.Dial("tcp", "", parsedUrl.Host)
	if err != nil {
		return
	}
	return newClient(parsedUrl.RawPath, parsedUrl.Host, origin, url, protocol, client, handshake)
}

/*
Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
cf. http://www.whatwg.org/specs/web-socket-protocol/
*/
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://www.whatwg.org/specs/web-socket-protocol/
*/
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
}

/*
Web Socket protocol handshake based on
http://www.whatwg.org/specs/web-socket-protocol/
(draft of http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol)
*/
func handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	// 4.1. Opening handshake.
	// Step 5.  send a request line.
	bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n")

	// Step 6-14. push request headers in fields.
	var fields vector.StringVector
	fields.Push("Upgrade: WebSocket\r\n")
	fields.Push("Connection: Upgrade\r\n")
	fields.Push("Host: " + host + "\r\n")
	fields.Push("Origin: " + origin + "\r\n")
	if protocol != "" {
		fields.Push("Sec-WebSocket-Protocol: " + protocol + "\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()
	fields.Push("Sec-WebSocket-Key1: " + key1 + "\r\n")
	fields.Push("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. genearte 8 bytes random key.
	key3 := generateKey3()
	// 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, "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["Upgrade"] != "WebSocket" ||
		strings.ToLower(resp.Header["Connection"]) != "upgrade" {
		return ErrBadUpgrade
	}

	if resp.Header["Sec-Websocket-Origin"] != origin {
		return ErrBadWebSocketOrigin
	}

	if resp.Header["Sec-Websocket-Location"] != location {
		return ErrBadWebSocketLocation
	}

	if protocol != "" && resp.Header["Sec-Websocket-Protocol"] != protocol {
		return ErrBadWebSocketProtocol
	}

	// Step 42-43. get expected data from challange 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
}

/*
Handhake described in (soon obsolete)
draft-hixie-thewebsocket-protocol-75.
*/
func draft75handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n")
	bw.WriteString("Upgrade: WebSocket\r\n")
	bw.WriteString("Connection: Upgrade\r\n")
	bw.WriteString("Host: " + host + "\r\n")
	bw.WriteString("Origin: " + origin + "\r\n")
	if protocol != "" {
		bw.WriteString("WebSocket-Protocol: " + protocol + "\r\n")
	}
	bw.WriteString("\r\n")
	bw.Flush()
	resp, err := http.ReadResponse(br, "GET")
	if err != nil {
		return
	}
	if resp.Status != "101 Web Socket Protocol Handshake" {
		return ErrBadStatus
	}
	if resp.Header["Upgrade"] != "WebSocket" ||
		resp.Header["Connection"] != "Upgrade" {
		return ErrBadUpgrade
	}
	if resp.Header["Websocket-Origin"] != origin {
		return ErrBadWebSocketOrigin
	}
	if resp.Header["Websocket-Location"] != location {
		return ErrBadWebSocketLocation
	}
	if protocol != "" && resp.Header["Websocket-Protocol"] != protocol {
		return ErrBadWebSocketProtocol
	}
	return
}
