|
@@ -24,7 +24,10 @@ import (
|
|
|
var serverAddr string
|
|
var serverAddr string
|
|
|
var once sync.Once
|
|
var once sync.Once
|
|
|
|
|
|
|
|
-func echoServer(ws *Conn) { io.Copy(ws, ws) }
|
|
|
|
|
|
|
+func echoServer(ws *Conn) {
|
|
|
|
|
+ defer ws.Close()
|
|
|
|
|
+ io.Copy(ws, ws)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
type Count struct {
|
|
type Count struct {
|
|
|
S string
|
|
S string
|
|
@@ -32,6 +35,7 @@ type Count struct {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func countServer(ws *Conn) {
|
|
func countServer(ws *Conn) {
|
|
|
|
|
+ defer ws.Close()
|
|
|
for {
|
|
for {
|
|
|
var count Count
|
|
var count Count
|
|
|
err := JSON.Receive(ws, &count)
|
|
err := JSON.Receive(ws, &count)
|
|
@@ -47,6 +51,55 @@ func countServer(ws *Conn) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+type testCtrlAndDataHandler struct {
|
|
|
|
|
+ hybiFrameHandler
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (h *testCtrlAndDataHandler) WritePing(b []byte) (int, error) {
|
|
|
|
|
+ h.hybiFrameHandler.conn.wio.Lock()
|
|
|
|
|
+ defer h.hybiFrameHandler.conn.wio.Unlock()
|
|
|
|
|
+ w, err := h.hybiFrameHandler.conn.frameWriterFactory.NewFrameWriter(PingFrame)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return 0, err
|
|
|
|
|
+ }
|
|
|
|
|
+ n, err := w.Write(b)
|
|
|
|
|
+ w.Close()
|
|
|
|
|
+ return n, err
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func ctrlAndDataServer(ws *Conn) {
|
|
|
|
|
+ defer ws.Close()
|
|
|
|
|
+ h := &testCtrlAndDataHandler{hybiFrameHandler: hybiFrameHandler{conn: ws}}
|
|
|
|
|
+ ws.frameHandler = h
|
|
|
|
|
+
|
|
|
|
|
+ go func() {
|
|
|
|
|
+ for i := 0; ; i++ {
|
|
|
|
|
+ var b []byte
|
|
|
|
|
+ if i%2 != 0 { // with or without payload
|
|
|
|
|
+ b = []byte(fmt.Sprintf("#%d-CONTROL-FRAME-FROM-SERVER", i))
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := h.WritePing(b); err != nil {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := h.WritePong(b); err != nil { // unsolicited pong
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ time.Sleep(10 * time.Millisecond)
|
|
|
|
|
+ }
|
|
|
|
|
+ }()
|
|
|
|
|
+
|
|
|
|
|
+ b := make([]byte, 128)
|
|
|
|
|
+ for {
|
|
|
|
|
+ n, err := ws.Read(b)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := ws.Write(b[:n]); err != nil {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func subProtocolHandshake(config *Config, req *http.Request) error {
|
|
func subProtocolHandshake(config *Config, req *http.Request) error {
|
|
|
for _, proto := range config.Protocol {
|
|
for _, proto := range config.Protocol {
|
|
|
if proto == "chat" {
|
|
if proto == "chat" {
|
|
@@ -66,6 +119,7 @@ func subProtoServer(ws *Conn) {
|
|
|
func startServer() {
|
|
func startServer() {
|
|
|
http.Handle("/echo", Handler(echoServer))
|
|
http.Handle("/echo", Handler(echoServer))
|
|
|
http.Handle("/count", Handler(countServer))
|
|
http.Handle("/count", Handler(countServer))
|
|
|
|
|
+ http.Handle("/ctrldata", Handler(ctrlAndDataServer))
|
|
|
subproto := Server{
|
|
subproto := Server{
|
|
|
Handshake: subProtocolHandshake,
|
|
Handshake: subProtocolHandshake,
|
|
|
Handler: Handler(subProtoServer),
|
|
Handler: Handler(subProtoServer),
|
|
@@ -492,3 +546,42 @@ func TestOrigin(t *testing.T) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+func TestCtrlAndData(t *testing.T) {
|
|
|
|
|
+ once.Do(startServer)
|
|
|
|
|
+
|
|
|
|
|
+ c, err := net.Dial("tcp", serverAddr)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ ws, err := NewClient(newConfig(t, "/ctrldata"), c)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ t.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ defer ws.Close()
|
|
|
|
|
+
|
|
|
|
|
+ h := &testCtrlAndDataHandler{hybiFrameHandler: hybiFrameHandler{conn: ws}}
|
|
|
|
|
+ ws.frameHandler = h
|
|
|
|
|
+
|
|
|
|
|
+ b := make([]byte, 128)
|
|
|
|
|
+ for i := 0; i < 2; i++ {
|
|
|
|
|
+ data := []byte(fmt.Sprintf("#%d-DATA-FRAME-FROM-CLIENT", i))
|
|
|
|
|
+ if _, err := ws.Write(data); err != nil {
|
|
|
|
|
+ t.Fatalf("#%d: %v", i, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ var ctrl []byte
|
|
|
|
|
+ if i%2 != 0 { // with or without payload
|
|
|
|
|
+ ctrl = []byte(fmt.Sprintf("#%d-CONTROL-FRAME-FROM-CLIENT", i))
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := h.WritePing(ctrl); err != nil {
|
|
|
|
|
+ t.Fatalf("#%d: %v", i, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ n, err := ws.Read(b)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ t.Fatalf("#%d: %v", i, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if !bytes.Equal(b[:n], data) {
|
|
|
|
|
+ t.Fatalf("#%d: got %v; want %v", i, b[:n], data)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|