]> Cypherpunks repositories - gostls13.git/commitdiff
websocket: add mutex to make websocket full-duplex
authorFumitoshi Ukai <ukai@google.com>
Fri, 23 Sep 2011 01:49:24 +0000 (21:49 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 23 Sep 2011 01:49:24 +0000 (21:49 -0400)
One benefit of websocket is that it is full-duplex so that it could
send and receive at the same time.
This CL makes websocket goroutine safe, so user could use websocket
both on goroutine for read and on goroutine for write.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5058043

src/pkg/websocket/hixie.go
src/pkg/websocket/hybi.go
src/pkg/websocket/websocket.go

index b755a5c6a619e5748c2cb81e61b53071334d5dbb..43de8a780087ebc79071e7274753758ce85c1178 100644 (file)
@@ -235,6 +235,8 @@ func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader,
 }
 
 func (handler *hixiFrameHandler) WriteClose(_ int) (err os.Error) {
+       handler.conn.wio.Lock()
+       defer handler.conn.wio.Unlock()
        closingFrame := []byte{'\xff', '\x00'}
        handler.conn.buf.Write(closingFrame)
        return handler.conn.buf.Flush()
index cad47182d6bb7646e4b811706a92f04a928e11b6..c4d990d6d882a3cd783a0b4814f7802f375fcf79 100644 (file)
@@ -288,6 +288,8 @@ func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader,
 }
 
 func (handler *hybiFrameHandler) WriteClose(status int) (err os.Error) {
+       handler.conn.wio.Lock()
+       defer handler.conn.wio.Unlock()
        w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
        if err != nil {
                return err
@@ -300,6 +302,8 @@ func (handler *hybiFrameHandler) WriteClose(status int) (err os.Error) {
 }
 
 func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err os.Error) {
+       handler.conn.wio.Lock()
+       defer handler.conn.wio.Unlock()
        w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
        if err != nil {
                return 0, err
index d57d1149c853ac3a056a428113bd3b44d0196bc9..1855705c99e0d7957ee69b5eae5514cb1abf4395 100644 (file)
@@ -15,6 +15,7 @@ import (
        "json"
        "net"
        "os"
+       "sync"
        "url"
 )
 
@@ -147,9 +148,11 @@ type Conn struct {
        buf *bufio.ReadWriter
        rwc io.ReadWriteCloser
 
+       rio sync.Mutex
        frameReaderFactory
        frameReader
 
+       wio sync.Mutex
        frameWriterFactory
 
        frameHandler
@@ -163,6 +166,8 @@ type Conn struct {
 // will read the rest of the frame data.
 // it reads Text frame or Binary frame.
 func (ws *Conn) Read(msg []byte) (n int, err os.Error) {
+       ws.rio.Lock()
+       defer ws.rio.Unlock()
 again:
        if ws.frameReader == nil {
                frame, err := ws.frameReaderFactory.NewFrameReader()
@@ -191,6 +196,8 @@ again:
 // Write implements the io.Writer interface:
 // it writes data as a frame to the WebSocket connection.
 func (ws *Conn) Write(msg []byte) (n int, err os.Error) {
+       ws.wio.Lock()
+       defer ws.wio.Unlock()
        w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
        if err != nil {
                return 0, err
@@ -279,6 +286,8 @@ func (cd Codec) Send(ws *Conn, v interface{}) (err os.Error) {
        if err != nil {
                return err
        }
+       ws.wio.Lock()
+       defer ws.wio.Unlock()
        w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
        _, err = w.Write(data)
        w.Close()
@@ -287,6 +296,8 @@ func (cd Codec) Send(ws *Conn, v interface{}) (err os.Error) {
 
 // Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
 func (cd Codec) Receive(ws *Conn, v interface{}) (err os.Error) {
+       ws.rio.Lock()
+       defer ws.rio.Unlock()
        if ws.frameReader != nil {
                _, err = io.Copy(ioutil.Discard, ws.frameReader)
                if err != nil {