|
3 | 3 | package websocket
|
4 | 4 |
|
5 | 5 | import (
|
| 6 | + "compress/flate" |
6 | 7 | "io"
|
7 | 8 | "net/http"
|
8 | 9 | "sync"
|
9 |
| - |
10 |
| - "github.com/klauspost/compress/flate" |
11 | 10 | )
|
12 | 11 |
|
13 | 12 | // CompressionMode represents the modes available to the deflate extension.
|
14 | 13 | // See https://tools.ietf.org/html/rfc7692
|
15 |
| -// |
16 |
| -// A compatibility layer is implemented for the older deflate-frame extension used |
17 |
| -// by safari. See https://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06 |
18 |
| -// It will work the same in every way except that we cannot signal to the peer we |
19 |
| -// want to use no context takeover on our side, we can only signal that they should. |
20 |
| -// It is however currently disabled due to Safari bugs. See https://github.com/nhooyr/websocket/issues/218 |
21 | 14 | type CompressionMode int
|
22 | 15 |
|
23 | 16 | const (
|
24 |
| - // CompressionNoContextTakeover grabs a new flate.Reader and flate.Writer as needed |
25 |
| - // for every message. This applies to both server and client side. |
| 17 | + // CompressionDisabled disables the deflate extension. |
26 | 18 | //
|
27 |
| - // This means less efficient compression as the sliding window from previous messages |
28 |
| - // will not be used but the memory overhead will be lower if the connections |
29 |
| - // are long lived and seldom used. |
| 19 | + // Use this if you are using a predominantly binary protocol with very |
| 20 | + // little duplication in between messages or CPU and memory are more |
| 21 | + // important than bandwidth. |
30 | 22 | //
|
31 |
| - // The message will only be compressed if greater than 512 bytes. |
32 |
| - CompressionNoContextTakeover CompressionMode = iota |
| 23 | + // This is the default. |
| 24 | + CompressionDisabled CompressionMode = iota |
33 | 25 |
|
34 |
| - // CompressionContextTakeover uses a flate.Reader and flate.Writer per connection. |
35 |
| - // This enables reusing the sliding window from previous messages. |
| 26 | + // CompressionContextTakeover uses a 32 kB sliding window and flate.Writer per connection. |
| 27 | + // It reusing the sliding window from previous messages. |
36 | 28 | // As most WebSocket protocols are repetitive, this can be very efficient.
|
37 |
| - // It carries an overhead of 8 kB for every connection compared to CompressionNoContextTakeover. |
| 29 | + // It carries an overhead of 32 kB + 1.2 MB for every connection compared to CompressionNoContextTakeover. |
| 30 | + // |
| 31 | + // Sometime in the future it will carry 65 kB overhead instead once https://github.com/golang/go/issues/36919 |
| 32 | + // is fixed. |
38 | 33 | //
|
39 | 34 | // If the peer negotiates NoContextTakeover on the client or server side, it will be
|
40 | 35 | // used instead as this is required by the RFC.
|
41 | 36 | CompressionContextTakeover
|
42 | 37 |
|
43 |
| - // CompressionDisabled disables the deflate extension. |
| 38 | + // CompressionNoContextTakeover grabs a new flate.Reader and flate.Writer as needed |
| 39 | + // for every message. This applies to both server and client side. |
44 | 40 | //
|
45 |
| - // Use this if you are using a predominantly binary protocol with very |
46 |
| - // little duplication in between messages or CPU and memory are more |
47 |
| - // important than bandwidth. |
48 |
| - CompressionDisabled |
| 41 | + // This means less efficient compression as the sliding window from previous messages |
| 42 | + // will not be used but the memory overhead will be lower if the connections |
| 43 | + // are long lived and seldom used. |
| 44 | + // |
| 45 | + // The message will only be compressed if greater than 512 bytes. |
| 46 | + CompressionNoContextTakeover |
49 | 47 | )
|
50 | 48 |
|
51 | 49 | func (m CompressionMode) opts() *compressionOptions {
|
@@ -146,6 +144,22 @@ func putFlateReader(fr io.Reader) {
|
146 | 144 | flateReaderPool.Put(fr)
|
147 | 145 | }
|
148 | 146 |
|
| 147 | +var flateWriterPool sync.Pool |
| 148 | + |
| 149 | +func getFlateWriter(w io.Writer) *flate.Writer { |
| 150 | + fw, ok := flateWriterPool.Get().(*flate.Writer) |
| 151 | + if !ok { |
| 152 | + fw, _ = flate.NewWriter(w, flate.BestSpeed) |
| 153 | + return fw |
| 154 | + } |
| 155 | + fw.Reset(w) |
| 156 | + return fw |
| 157 | +} |
| 158 | + |
| 159 | +func putFlateWriter(w *flate.Writer) { |
| 160 | + flateWriterPool.Put(w) |
| 161 | +} |
| 162 | + |
149 | 163 | type slidingWindow struct {
|
150 | 164 | buf []byte
|
151 | 165 | }
|
|
0 commit comments