1 module hunt.http.codec.websocket.model.extension.compress.PerMessageDeflateExtension; 2 3 // import hunt.http.Exceptions.BadPayloadException; 4 // import hunt.http.WebSocketFrame; 5 // import hunt.http.codec.websocket.model.ExtensionConfig; 6 // import hunt.http.WebSocketCommon; 7 // import hunt.util.Common; 8 // import hunt.logging; 9 10 11 // import hunt.io.ByteBuffer; 12 // import java.util.zip.DataFormatException; 13 14 // /** 15 // * Per Message Deflate Compression extension for WebSocket. 16 // * <p> 17 // * Attempts to follow <a href="https://tools.ietf.org/html/rfc7692">Compression Extensions for WebSocket</a> 18 // */ 19 // class PerMessageDeflateExtension : CompressExtension { 20 21 22 // private ExtensionConfig configRequested; 23 // private ExtensionConfig configNegotiated; 24 // private bool incomingContextTakeover = true; 25 // private bool outgoingContextTakeover = true; 26 // private bool incomingCompressed; 27 28 // override 29 // string getName() { 30 // return "permessage-deflate"; 31 // } 32 33 // override 34 // void incomingFrame(Frame frame) { 35 // // Incoming frames are always non concurrent because 36 // // they are read and parsed with a single thread, and 37 // // therefore there is no need for synchronization. 38 39 // // This extension requires the RSV1 bit set only in the first frame. 40 // // Subsequent continuation frames don't have RSV1 set, but are compressed. 41 // if (frame.getType().isData()) { 42 // incomingCompressed = frame.isRsv1(); 43 // } 44 45 // if (OpCode.isControlFrame(frame.getOpCode()) || !incomingCompressed) { 46 // nextIncomingFrame(frame); 47 // return; 48 // } 49 50 // ByteAccumulator accumulator = newByteAccumulator(); 51 52 // try { 53 // ByteBuffer payload = frame.getPayload(); 54 // decompress(accumulator, payload); 55 // if (frame.isFin()) { 56 // decompress(accumulator, TAIL_BYTES_BUF.slice()); 57 // } 58 59 // forwardIncoming(frame, accumulator); 60 // } catch (DataFormatException e) { 61 // throw new BadPayloadException(e); 62 // } 63 64 // if (frame.isFin()) 65 // incomingCompressed = false; 66 // } 67 68 // override 69 // protected void nextIncomingFrame(Frame frame) { 70 // if (frame.isFin() && !incomingContextTakeover) { 71 // tracef("Incoming Context Reset"); 72 // decompressCount.set(0); 73 // getInflater().reset(); 74 // } 75 // super.nextIncomingFrame(frame); 76 // } 77 78 // override 79 // protected void nextOutgoingFrame(Frame frame, Callback callback) { 80 // if (frame.isFin() && !outgoingContextTakeover) { 81 // tracef("Outgoing Context Reset"); 82 // getDeflater().reset(); 83 // } 84 // super.nextOutgoingFrame(frame, callback); 85 // } 86 87 // override 88 // int getRsvUseMode() { 89 // return RSV_USE_ONLY_FIRST; 90 // } 91 92 // override 93 // int getTailDropMode() { 94 // return TAIL_DROP_FIN_ONLY; 95 // } 96 97 // override 98 // void setConfig(final ExtensionConfig config) { 99 // configRequested = new ExtensionConfig(config); 100 // configNegotiated = new ExtensionConfig(config.getName()); 101 102 // for (string key : config.getParameterKeys()) { 103 // key = key.trim(); 104 // switch (key) { 105 // case "client_max_window_bits": 106 // case "server_max_window_bits": { 107 // // Don't negotiate these parameters 108 // break; 109 // } 110 // case "client_no_context_takeover": { 111 // configNegotiated.setParameter("client_no_context_takeover"); 112 // switch (getPolicy().getBehavior()) { 113 // case CLIENT: 114 // incomingContextTakeover = false; 115 // break; 116 // case SERVER: 117 // outgoingContextTakeover = false; 118 // break; 119 // } 120 // break; 121 // } 122 // case "server_no_context_takeover": { 123 // configNegotiated.setParameter("server_no_context_takeover"); 124 // switch (getPolicy().getBehavior()) { 125 // case CLIENT: 126 // outgoingContextTakeover = false; 127 // break; 128 // case SERVER: 129 // incomingContextTakeover = false; 130 // break; 131 // } 132 // break; 133 // } 134 // default: { 135 // throw new IllegalArgumentException(); 136 // } 137 // } 138 // } 139 140 // tracef("config: outgoingContextTakover=%s, incomingContextTakeover=%s : %s", outgoingContextTakeover, incomingContextTakeover, this); 141 142 // super.setConfig(configNegotiated); 143 // } 144 145 // override 146 // string toString() { 147 // return string.format("%s[requested=\"%s\", negotiated=\"%s\"]", 148 // typeof(this).stringof, 149 // configRequested.getParameterizedName(), 150 // configNegotiated.getParameterizedName()); 151 // } 152 // }