go.net: initial code
Manual edits to README.
Moved from main Go repository, deleted Makefiles, ran gofix -r go1rename.
Tested with: go test code.google.com/p/go.net/...
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5574065
diff --git a/websocket/client.go b/websocket/client.go
new file mode 100644
index 0000000..89cdcda
--- /dev/null
+++ b/websocket/client.go
@@ -0,0 +1,137 @@
+// 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"
+ "crypto/tls"
+ "io"
+ "net"
+ "net/url"
+)
+
+// DialError is an error that occurs while dialling a websocket server.
+type DialError struct {
+ *Config
+ Err error
+}
+
+func (e *DialError) Error() string {
+ return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
+}
+
+// NewConfig creates a new WebSocket config for client connection.
+func NewConfig(server, origin string) (config *Config, err error) {
+ config = new(Config)
+ config.Version = ProtocolVersionHybi13
+ config.Location, err = url.ParseRequest(server)
+ if err != nil {
+ return
+ }
+ config.Origin, err = url.ParseRequest(origin)
+ if err != nil {
+ return
+ }
+ return
+}
+
+// NewClient creates a new WebSocket client connection over rwc.
+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
+ }
+ 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)
+ }
+ return
+}
+
+/*
+Dial opens a new client connection to a WebSocket.
+
+A trivial example client:
+
+ package main
+
+ import (
+ "log"
+ "net/http"
+ "strings"
+ "websocket"
+ )
+
+ func main() {
+ origin := "http://localhost/"
+ url := "ws://localhost/ws"
+ ws, err := websocket.Dial(url, "", origin)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
+ log.Fatal(err)
+ }
+ var msg = make([]byte, 512);
+ if n, err := ws.Read(msg); err != nil {
+ log.Fatal(err)
+ }
+ // use msg[0:n]
+ }
+*/
+func Dial(url_, protocol, origin string) (ws *Conn, err error) {
+ config, err := NewConfig(url_, origin)
+ if err != nil {
+ return nil, err
+ }
+ return DialConfig(config)
+}
+
+// DialConfig opens a new client connection to a WebSocket with a config.
+func DialConfig(config *Config) (ws *Conn, err error) {
+ var client net.Conn
+ if config.Location == nil {
+ return nil, &DialError{config, ErrBadWebSocketLocation}
+ }
+ if config.Origin == nil {
+ return nil, &DialError{config, ErrBadWebSocketOrigin}
+ }
+ switch config.Location.Scheme {
+ case "ws":
+ client, err = net.Dial("tcp", config.Location.Host)
+
+ case "wss":
+ client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
+
+ default:
+ err = ErrBadScheme
+ }
+ if err != nil {
+ goto Error
+ }
+
+ ws, err = NewClient(config, client)
+ if err != nil {
+ goto Error
+ }
+ return
+
+Error:
+ return nil, &DialError{config, err}
+}