176 lines
4.4 KiB
Go
176 lines
4.4 KiB
Go
|
package ws
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"github.com/docker/spdystream"
|
||
|
"github.com/gorilla/websocket"
|
||
|
"io"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"net/http/httptest"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
var upgrader = websocket.Upgrader{
|
||
|
ReadBufferSize: 1024,
|
||
|
WriteBufferSize: 1024,
|
||
|
}
|
||
|
|
||
|
var serverSpdyConn *spdystream.Connection
|
||
|
|
||
|
// Connect to the Websocket endpoint at ws://localhost
|
||
|
// using SPDY over Websockets framing.
|
||
|
func ExampleConn() {
|
||
|
wsconn, _, _ := websocket.DefaultDialer.Dial("ws://localhost/", http.Header{"Origin": {"http://localhost/"}})
|
||
|
conn, _ := spdystream.NewConnection(NewConnection(wsconn), false)
|
||
|
go conn.Serve(spdystream.NoOpStreamHandler, spdystream.NoAuthHandler)
|
||
|
stream, _ := conn.CreateStream(http.Header{}, nil, false)
|
||
|
stream.Wait()
|
||
|
}
|
||
|
|
||
|
func serveWs(w http.ResponseWriter, r *http.Request) {
|
||
|
if r.Method != "GET" {
|
||
|
http.Error(w, "Method not allowed", 405)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ws, err := upgrader.Upgrade(w, r, nil)
|
||
|
if err != nil {
|
||
|
if _, ok := err.(websocket.HandshakeError); !ok {
|
||
|
log.Println(err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
wrap := NewConnection(ws)
|
||
|
spdyConn, err := spdystream.NewConnection(wrap, true)
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
return
|
||
|
}
|
||
|
serverSpdyConn = spdyConn
|
||
|
go spdyConn.Serve(spdystream.MirrorStreamHandler, authStreamHandler)
|
||
|
}
|
||
|
|
||
|
func TestSpdyStreamOverWs(t *testing.T) {
|
||
|
server := httptest.NewServer(http.HandlerFunc(serveWs))
|
||
|
defer server.Close()
|
||
|
defer func() {
|
||
|
if serverSpdyConn != nil {
|
||
|
serverSpdyConn.Close()
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
wsconn, _, err := websocket.DefaultDialer.Dial(strings.Replace(server.URL, "http://", "ws://", 1), http.Header{"Origin": {server.URL}})
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
wrap := NewConnection(wsconn)
|
||
|
spdyConn, err := spdystream.NewConnection(wrap, false)
|
||
|
if err != nil {
|
||
|
defer wsconn.Close()
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer spdyConn.Close()
|
||
|
authenticated = true
|
||
|
go spdyConn.Serve(spdystream.NoOpStreamHandler, spdystream.RejectAuthHandler)
|
||
|
|
||
|
stream, streamErr := spdyConn.CreateStream(http.Header{}, nil, false)
|
||
|
if streamErr != nil {
|
||
|
t.Fatalf("Error creating stream: %s", streamErr)
|
||
|
}
|
||
|
|
||
|
waitErr := stream.Wait()
|
||
|
if waitErr != nil {
|
||
|
t.Fatalf("Error waiting for stream: %s", waitErr)
|
||
|
}
|
||
|
|
||
|
message := []byte("hello")
|
||
|
writeErr := stream.WriteData(message, false)
|
||
|
if writeErr != nil {
|
||
|
t.Fatalf("Error writing data")
|
||
|
}
|
||
|
|
||
|
buf := make([]byte, 10)
|
||
|
n, readErr := stream.Read(buf)
|
||
|
if readErr != nil {
|
||
|
t.Fatalf("Error reading data from stream: %s", readErr)
|
||
|
}
|
||
|
if n != 5 {
|
||
|
t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 5", n)
|
||
|
}
|
||
|
if bytes.Compare(buf[:n], message) != 0 {
|
||
|
t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", buf, message)
|
||
|
}
|
||
|
|
||
|
writeErr = stream.WriteData(message, true)
|
||
|
if writeErr != nil {
|
||
|
t.Fatalf("Error writing data")
|
||
|
}
|
||
|
|
||
|
smallBuf := make([]byte, 3)
|
||
|
n, readErr = stream.Read(smallBuf)
|
||
|
if readErr != nil {
|
||
|
t.Fatalf("Error reading data from stream: %s", readErr)
|
||
|
}
|
||
|
if n != 3 {
|
||
|
t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 3", n)
|
||
|
}
|
||
|
if bytes.Compare(smallBuf[:n], []byte("hel")) != 0 {
|
||
|
t.Fatalf("Did not receive expected message:\nActual: %s\nExpectd: %s", smallBuf[:n], message)
|
||
|
}
|
||
|
n, readErr = stream.Read(smallBuf)
|
||
|
if readErr != nil {
|
||
|
t.Fatalf("Error reading data from stream: %s", readErr)
|
||
|
}
|
||
|
if n != 2 {
|
||
|
t.Fatalf("Unexpected number of bytes read:\nActual: %d\nExpected: 2", n)
|
||
|
}
|
||
|
if bytes.Compare(smallBuf[:n], []byte("lo")) != 0 {
|
||
|
t.Fatalf("Did not receive expected message:\nActual: %s\nExpected: lo", smallBuf[:n])
|
||
|
}
|
||
|
|
||
|
n, readErr = stream.Read(buf)
|
||
|
if readErr != io.EOF {
|
||
|
t.Fatalf("Expected EOF reading from finished stream, read %d bytes", n)
|
||
|
}
|
||
|
|
||
|
streamCloseErr := stream.Close()
|
||
|
if streamCloseErr != nil {
|
||
|
t.Fatalf("Error closing stream: %s", streamCloseErr)
|
||
|
}
|
||
|
|
||
|
// Closing again should return nil
|
||
|
streamCloseErr = stream.Close()
|
||
|
if streamCloseErr != nil {
|
||
|
t.Fatalf("Error closing stream: %s", streamCloseErr)
|
||
|
}
|
||
|
|
||
|
authenticated = false
|
||
|
badStream, badStreamErr := spdyConn.CreateStream(http.Header{}, nil, false)
|
||
|
if badStreamErr != nil {
|
||
|
t.Fatalf("Error creating stream: %s", badStreamErr)
|
||
|
}
|
||
|
|
||
|
waitErr = badStream.Wait()
|
||
|
if waitErr == nil {
|
||
|
t.Fatalf("Did not receive error creating stream")
|
||
|
}
|
||
|
if waitErr != spdystream.ErrReset {
|
||
|
t.Fatalf("Unexpected error creating stream: %s", waitErr)
|
||
|
}
|
||
|
|
||
|
spdyCloseErr := spdyConn.Close()
|
||
|
if spdyCloseErr != nil {
|
||
|
t.Fatalf("Error closing spdy connection: %s", spdyCloseErr)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var authenticated bool
|
||
|
|
||
|
func authStreamHandler(header http.Header, slot uint8, parent uint32) bool {
|
||
|
return authenticated
|
||
|
}
|