mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Add WebSocket server framework hooked into http.
R=r, rsc https://golang.org/cl/156071
This commit is contained in:
parent
6e6125ffa4
commit
f9f0184e13
6 changed files with 418 additions and 0 deletions
136
src/pkg/websocket/client.go
Normal file
136
src/pkg/websocket/client.go
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
// 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";
|
||||
"http";
|
||||
"io";
|
||||
"net";
|
||||
"os";
|
||||
)
|
||||
|
||||
type ProtocolError struct {
|
||||
os.ErrorString;
|
||||
}
|
||||
|
||||
var (
|
||||
ErrBadStatus = &ProtocolError{"bad status"};
|
||||
ErrNoUpgrade = &ProtocolError{"no upgrade"};
|
||||
ErrBadUpgrade = &ProtocolError{"bad upgrade"};
|
||||
ErrNoWebSocketOrigin = &ProtocolError{"no WebSocket-Origin"};
|
||||
ErrBadWebSocketOrigin = &ProtocolError{"bad WebSocket-Origin"};
|
||||
ErrNoWebSocketLocation = &ProtocolError{"no WebSocket-Location"};
|
||||
ErrBadWebSocketLocation = &ProtocolError{"bad WebSocket-Location"};
|
||||
ErrNoWebSocketProtocol = &ProtocolError{"no WebSocket-Protocol"};
|
||||
ErrBadWebSocketProtocol = &ProtocolError{"bad WebSocket-Protocol"};
|
||||
)
|
||||
|
||||
// newClient creates a new Web Socket client connection.
|
||||
func newClient(resourceName, host, origin, location, protocol string, rwc io.ReadWriteCloser) (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 new Web Socket client connection.
|
||||
//
|
||||
// A trivial example client is:
|
||||
//
|
||||
// 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(strings.Bytes("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())
|
||||
// }
|
||||
// // 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.Path, parsedUrl.Host, origin, url, protocol, client);
|
||||
}
|
||||
|
||||
func handshake(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);
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Status != "101 Web Socket Protocol Handshake" {
|
||||
return ErrBadStatus
|
||||
}
|
||||
upgrade, found := resp.Header["Upgrade"];
|
||||
if !found {
|
||||
return ErrNoUpgrade
|
||||
}
|
||||
if upgrade != "WebSocket" {
|
||||
return ErrBadUpgrade
|
||||
}
|
||||
connection, found := resp.Header["Connection"];
|
||||
if !found || connection != "Upgrade" {
|
||||
return ErrBadUpgrade
|
||||
}
|
||||
|
||||
ws_origin, found := resp.Header["Websocket-Origin"];
|
||||
if !found {
|
||||
return ErrNoWebSocketOrigin
|
||||
}
|
||||
if ws_origin != origin {
|
||||
return ErrBadWebSocketOrigin
|
||||
}
|
||||
ws_location, found := resp.Header["Websocket-Location"];
|
||||
if !found {
|
||||
return ErrNoWebSocketLocation
|
||||
}
|
||||
if ws_location != location {
|
||||
return ErrBadWebSocketLocation
|
||||
}
|
||||
if protocol != "" {
|
||||
ws_protocol, found := resp.Header["Websocket-Protocol"];
|
||||
if !found {
|
||||
return ErrNoWebSocketProtocol
|
||||
}
|
||||
if ws_protocol != protocol {
|
||||
return ErrBadWebSocketProtocol
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue