Commit e4790b5f authored by Fumitoshi Ukai's avatar Fumitoshi Ukai Committed by Russ Cox

websocket: add mutex to make websocket full-duplex

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
parent 3dc3fa0d
......@@ -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()
......
......@@ -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
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment