@@ -13,7 +13,7 @@ import (
1313 "golang.org/x/xerrors"
1414)
1515
16- type control struct {
16+ type frame struct {
1717 opcode opcode
1818 payload []byte
1919}
@@ -42,7 +42,8 @@ type Conn struct {
4242 // ping on writeDone.
4343 // writeDone will be closed if the data message write errors.
4444 write chan MessageType
45- control chan control
45+ control chan frame
46+ fastWrite chan frame
4647 writeBytes chan []byte
4748 writeDone chan struct {}
4849 writeFlush chan struct {}
@@ -86,7 +87,8 @@ func (c *Conn) init() {
8687 c .closed = make (chan struct {})
8788
8889 c .write = make (chan MessageType )
89- c .control = make (chan control )
90+ c .control = make (chan frame )
91+ c .fastWrite = make (chan frame )
9092 c .writeBytes = make (chan []byte )
9193 c .writeDone = make (chan struct {})
9294 c .writeFlush = make (chan struct {})
@@ -103,6 +105,8 @@ func (c *Conn) init() {
103105 go c .readLoop ()
104106}
105107
108+ // We never mask inside here because our mask key is always 0,0,0,0.
109+ // See comment on secWebSocketKey.
106110func (c * Conn ) writeFrame (h header , p []byte ) {
107111 b2 := marshalHeader (h )
108112 _ , err := c .bw .Write (b2 )
@@ -126,14 +130,14 @@ func (c *Conn) writeFrame(h header, p []byte) {
126130 }
127131}
128132
129- func (c * Conn ) writeLoopControl ( control control ) {
133+ func (c * Conn ) writeLoopFastWrite ( frame frame ) {
130134 h := header {
131135 fin : true ,
132- opcode : control .opcode ,
133- payloadLength : int64 (len (control .payload )),
136+ opcode : frame .opcode ,
137+ payloadLength : int64 (len (frame .payload )),
134138 masked : c .client ,
135139 }
136- c .writeFrame (h , control .payload )
140+ c .writeFrame (h , frame .payload )
137141 select {
138142 case <- c .closed :
139143 case c .writeDone <- struct {}{}:
@@ -150,7 +154,11 @@ messageLoop:
150154 case <- c .closed :
151155 return
152156 case control := <- c .control :
153- c .writeLoopControl (control )
157+ c .writeLoopFastWrite (control )
158+ continue
159+ case frame := <- c .fastWrite :
160+ c .writeLoopFastWrite (frame )
161+ continue
154162 case dataType = <- c .write :
155163 }
156164
@@ -160,7 +168,7 @@ messageLoop:
160168 case <- c .closed :
161169 return
162170 case control := <- c .control :
163- c .writeLoopControl (control )
171+ c .writeLoopFastWrite (control )
164172 case b := <- c .writeBytes :
165173 h := header {
166174 fin : false ,
@@ -220,7 +228,7 @@ func (c *Conn) handleControl(h header) {
220228 }
221229
222230 if h .masked {
223- xor (h .maskKey , 0 , b )
231+ fastXOR (h .maskKey , 0 , b )
224232 }
225233
226234 switch h .opcode {
@@ -314,7 +322,7 @@ func (c *Conn) dataReadLoop(h header) (err error) {
314322 left -= int64 (len (b ))
315323
316324 if h .masked {
317- maskPos = xor (h .maskKey , maskPos , b )
325+ maskPos = fastXOR (h .maskKey , maskPos , b )
318326 }
319327
320328 // Must set this before we signal the read is done.
@@ -341,7 +349,7 @@ func (c *Conn) writePong(p []byte) error {
341349 ctx , cancel := context .WithTimeout (context .Background (), time .Second * 5 )
342350 defer cancel ()
343351
344- err := c .writeControl (ctx , opPong , p )
352+ err := c .writeSingleFrame (ctx , opPong , p )
345353 return err
346354}
347355
@@ -384,7 +392,7 @@ func (c *Conn) writeClose(p []byte, cerr CloseError) error {
384392 ctx , cancel := context .WithTimeout (context .Background (), time .Second * 5 )
385393 defer cancel ()
386394
387- err := c .writeControl (ctx , opClose , p )
395+ err := c .writeSingleFrame (ctx , opClose , p )
388396
389397 c .close (cerr )
390398
@@ -399,11 +407,15 @@ func (c *Conn) writeClose(p []byte, cerr CloseError) error {
399407 return nil
400408}
401409
402- func (c * Conn ) writeControl (ctx context.Context , opcode opcode , p []byte ) error {
410+ func (c * Conn ) writeSingleFrame (ctx context.Context , opcode opcode , p []byte ) error {
411+ ch := c .fastWrite
412+ if opcode .controlOp () {
413+ ch = c .control
414+ }
403415 select {
404416 case <- c .closed :
405417 return c .closeErr
406- case c . control <- control {
418+ case ch <- frame {
407419 opcode : opcode ,
408420 payload : p ,
409421 }:
0 commit comments