1
0
mirror of https://github.com/golang/go synced 2024-09-28 16:14:28 -06:00

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
This commit is contained in:
Fumitoshi Ukai 2011-09-22 21:49:24 -04:00 committed by Russ Cox
parent 3dc3fa0d8c
commit e4790b5fa4
3 changed files with 17 additions and 0 deletions

View 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()

View 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

View 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 {