summaryrefslogtreecommitdiff
path: root/src/pkg/websocket/client.go
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-01-17 12:40:45 +0100
committerOndřej Surý <ondrej@sury.org>2011-01-17 12:40:45 +0100
commit3e45412327a2654a77944249962b3652e6142299 (patch)
treebc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/websocket/client.go
parentc533680039762cacbc37db8dc7eed074c3e497be (diff)
downloadgolang-3e45412327a2654a77944249962b3652e6142299.tar.gz
Imported Upstream version 2011.01.12upstream/2011.01.12
Diffstat (limited to 'src/pkg/websocket/client.go')
-rw-r--r--src/pkg/websocket/client.go113
1 files changed, 59 insertions, 54 deletions
diff --git a/src/pkg/websocket/client.go b/src/pkg/websocket/client.go
index 2966450a6..091345944 100644
--- a/src/pkg/websocket/client.go
+++ b/src/pkg/websocket/client.go
@@ -5,11 +5,10 @@
package websocket
import (
- "encoding/binary"
"bufio"
"bytes"
"container/vector"
- "crypto/md5"
+ "crypto/tls"
"fmt"
"http"
"io"
@@ -24,6 +23,7 @@ type ProtocolError struct {
}
var (
+ ErrBadScheme = os.ErrorString("bad scheme")
ErrBadStatus = &ProtocolError{"bad status"}
ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
@@ -33,6 +33,17 @@ var (
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++ {
@@ -61,8 +72,9 @@ func newClient(resourceName, host, origin, location, protocol string, rwc io.Rea
}
/*
- Dial opens a new client connection to a Web Socket.
- A trivial example client is:
+Dial opens a new client connection to a Web Socket.
+
+A trivial example client:
package main
@@ -87,21 +99,40 @@ func newClient(resourceName, host, origin, location, protocol string, rwc io.Rea
}
*/
func Dial(url, protocol, origin string) (ws *Conn, err os.Error) {
+ var client net.Conn
+
parsedUrl, err := http.ParseURL(url)
if err != nil {
- return
+ 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
}
- client, err := net.Dial("tcp", "", parsedUrl.Host)
if err != nil {
- return
+ goto Error
}
- return newClient(parsedUrl.RawPath, parsedUrl.Host, origin, url, protocol, client, handshake)
+
+ 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/
+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.
@@ -123,14 +154,7 @@ func generateKeyNumber() (key string, number uint32) {
// to U+0039 DIGIT NINE (9).
key = fmt.Sprintf("%d", product)
- // 21. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
- // posisions.
- for i := 0; i < spaces; i++ {
- pos := rand.Intn(len(key)-1) + 1
- key = key[0:pos] + " " + key[pos:]
- }
-
- // 22. Insert between one and twelve random characters from the ranges
+ // 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
@@ -139,13 +163,20 @@ func generateKeyNumber() (key string, number uint32) {
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/
+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
@@ -158,35 +189,9 @@ func generateKey3() (key []byte) {
}
/*
- Gets expected from challenge as described in 4.1 Opening handshake
- Step 42 to 43.
- cf. http://www.whatwg.org/specs/web-socket-protocol/
-*/
-func getExpectedForChallenge(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)
- challengeBuf := bytes.NewBuffer(challenge)
- binary.Write(challengeBuf, binary.BigEndian, number1)
- binary.Write(challengeBuf, binary.BigEndian, 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
-}
-
-/*
- Web Socket protocol handshake based on
- http://www.whatwg.org/specs/web-socket-protocol/
- (draft of http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol)
+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.
@@ -258,7 +263,7 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio.
}
// Step 42-43. get expected data from challange data.
- expected, err := getExpectedForChallenge(number1, number2, key3)
+ expected, err := getChallengeResponse(number1, number2, key3)
if err != nil {
return err
}
@@ -278,8 +283,8 @@ func handshake(resourceName, host, origin, location, protocol string, br *bufio.
}
/*
- Handhake described in (soon obsolete)
- draft-hixie-thewebsocket-protocol-75.
+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")