mirror of
https://github.com/golang/go
synced 2024-11-21 20:54:45 -07:00
websocket: Add support for secure WebSockets
Fixes #842. Fixes #1061. R=rsc CC=golang-dev https://golang.org/cl/2119042
This commit is contained in:
parent
befecf6b59
commit
50e0fb4c79
@ -63,6 +63,7 @@ type Conn struct {
|
||||
header map[string]string // reply header parameters
|
||||
written int64 // number of bytes written in body
|
||||
status int // status code passed to WriteHeader
|
||||
usingTLS bool // a flag indicating connection over TLS
|
||||
}
|
||||
|
||||
// Create new connection from rwc.
|
||||
@ -73,6 +74,7 @@ func newConn(rwc net.Conn, handler Handler) (c *Conn, err os.Error) {
|
||||
}
|
||||
c.handler = handler
|
||||
c.rwc = rwc
|
||||
_, c.usingTLS = rwc.(*tls.Conn)
|
||||
br := bufio.NewReader(rwc)
|
||||
bw := bufio.NewWriter(rwc)
|
||||
c.buf = bufio.NewReadWriter(br, bw)
|
||||
@ -151,6 +153,11 @@ func (c *Conn) readRequest() (req *Request, err os.Error) {
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// UsingTLS returns true if the connection uses transport layer security (TLS).
|
||||
func (c *Conn) UsingTLS() bool {
|
||||
return c.usingTLS
|
||||
}
|
||||
|
||||
// SetHeader sets a header line in the eventual reply.
|
||||
// For example, SetHeader("Content-Type", "text/html; charset=utf-8")
|
||||
// will result in the header line
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"container/vector"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"http"
|
||||
"io"
|
||||
@ -22,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"}
|
||||
@ -31,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++ {
|
||||
@ -86,15 +99,35 @@ A trivial example client:
|
||||
}
|
||||
*/
|
||||
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)
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -97,7 +97,12 @@ func (f Handler) ServeHTTP(c *http.Conn, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
location := "ws://" + req.Host + req.URL.RawPath
|
||||
var location string
|
||||
if c.UsingTLS() {
|
||||
location = "wss://" + req.Host + req.URL.RawPath
|
||||
} else {
|
||||
location = "ws://" + req.Host + req.URL.RawPath
|
||||
}
|
||||
|
||||
// Step 4. get key number in Sec-WebSocket-Key<n> fields.
|
||||
keyNumber1 := getKeyNumber(key1)
|
||||
@ -185,7 +190,13 @@ func (f Draft75Handler) ServeHTTP(c *http.Conn, req *http.Request) {
|
||||
return
|
||||
}
|
||||
defer rwc.Close()
|
||||
location := "ws://" + req.Host + req.URL.RawPath
|
||||
|
||||
var location string
|
||||
if c.UsingTLS() {
|
||||
location = "wss://" + req.Host + req.URL.RawPath
|
||||
} else {
|
||||
location = "ws://" + req.Host + req.URL.RawPath
|
||||
}
|
||||
|
||||
// TODO(ukai): verify origin,location,protocol.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user