diff options
Diffstat (limited to 'src/pkg/websocket/client.go')
| -rw-r--r-- | src/pkg/websocket/client.go | 323 | 
1 files changed, 0 insertions, 323 deletions
| diff --git a/src/pkg/websocket/client.go b/src/pkg/websocket/client.go deleted file mode 100644 index f066a1832..000000000 --- a/src/pkg/websocket/client.go +++ /dev/null @@ -1,323 +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 - -import ( -	"bufio" -	"bytes" -	"container/vector" -	"crypto/tls" -	"fmt" -	"http" -	"io" -	"net" -	"os" -	"rand" -	"strings" -) - -type ProtocolError struct { -	ErrorString string -} - -func (err *ProtocolError) String() string { return string(err.ErrorString) } - -var ( -	ErrBadScheme            = &ProtocolError{"bad scheme"} -	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 challenge/response"} -	secKeyRandomChars       [0x30 - 0x21 + 0x7F - 0x3A]byte -) - -type DialError struct { -	URL      string -	Protocol string -	Origin   string -	Error    os.Error -} - -func (e *DialError) String() string { -	return "websocket.Dial " + e.URL + ": " + e.Error.String() -} - -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) { -	var client net.Conn - -	parsedUrl, err := http.ParseURL(url) -	if err != nil { -		goto Error -	} - -	switch parsedUrl.Scheme { -	case "ws": -		client, err = net.Dial("tcp", parsedUrl.Host) - -	case "wss": -		client, err = tls.Dial("tcp", parsedUrl.Host, nil) - -	default: -		err = ErrBadScheme -	} -	if err != nil { -		goto Error -	} - -	ws, err = newClient(parsedUrl.RawPath, parsedUrl.Host, origin, url, protocol, client, handshake) -	if err != nil { -		goto Error -	} -	return - -Error: -	return nil, &DialError{url, protocol, origin, err} -} - -/* -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. generate 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, &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") != origin { -		return ErrBadWebSocketOrigin -	} - -	if resp.Header.Get("Sec-Websocket-Location") != location { -		return ErrBadWebSocketLocation -	} - -	if protocol != "" && resp.Header.Get("Sec-Websocket-Protocol") != protocol { -		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 -} - -/* -Handshake 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, &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") != origin { -		return ErrBadWebSocketOrigin -	} -	if resp.Header.Get("Websocket-Location") != location { -		return ErrBadWebSocketLocation -	} -	if protocol != "" && resp.Header.Get("Websocket-Protocol") != protocol { -		return ErrBadWebSocketProtocol -	} -	return -} | 
