1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.common.extensions.compress;
20
21
22 import java.nio.ByteBuffer;
23
24 import org.eclipse.jetty.util.log.Log;
25 import org.eclipse.jetty.util.log.Logger;
26 import org.eclipse.jetty.websocket.api.WriteCallback;
27 import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
28 import org.eclipse.jetty.websocket.api.extensions.Frame;
29 import org.eclipse.jetty.websocket.common.WebSocketFrame;
30 import org.eclipse.jetty.websocket.common.extensions.AbstractExtension;
31
32
33
34
35
36
37 public class MessageCompressionExtension extends AbstractExtension
38 {
39 private static final Logger LOG = Log.getLogger(MessageCompressionExtension.class);
40
41 private CompressionMethod method;
42
43 @Override
44 public void incomingFrame(Frame frame)
45 {
46 if (frame.getType().isControl() || !frame.isRsv1())
47 {
48
49 nextIncomingFrame(frame);
50 return;
51 }
52
53 ByteBuffer data = frame.getPayload();
54 method.decompress().input(data);
55 while (!method.decompress().isDone())
56 {
57 ByteBuffer uncompressed = method.decompress().process();
58 if (uncompressed == null)
59 {
60 continue;
61 }
62 WebSocketFrame out = new WebSocketFrame(frame).setPayload(uncompressed);
63 if (!method.decompress().isDone())
64 {
65 out.setFin(false);
66 }
67 out.setRsv1(false);
68 nextIncomingFrame(out);
69 }
70
71
72 if (frame.isFin())
73 {
74 method.decompress().end();
75 }
76 }
77
78
79
80
81 @Override
82 public boolean isRsv1User()
83 {
84 return true;
85 }
86
87 @Override
88 public boolean isTextDataDecoder()
89 {
90
91 return true;
92 }
93
94 @Override
95 public void outgoingFrame(Frame frame, WriteCallback callback)
96 {
97 if (frame.getType().isControl())
98 {
99
100 nextOutgoingFrame(frame,callback);
101 return;
102 }
103
104 ByteBuffer data = frame.getPayload();
105
106 method.compress().input(data);
107 while (!method.compress().isDone())
108 {
109 ByteBuffer buf = method.compress().process();
110 WebSocketFrame out = new WebSocketFrame(frame).setPayload(buf);
111 out.setRsv1(true);
112 if (!method.compress().isDone())
113 {
114 out.setFin(false);
115
116 nextOutgoingFrame(out,null);
117 }
118 else
119 {
120
121 nextOutgoingFrame(out,callback);
122 }
123 }
124
125
126 if (frame.isFin())
127 {
128 method.compress().end();
129 }
130 }
131
132 @Override
133 public void setConfig(ExtensionConfig config)
134 {
135 super.setConfig(config);
136
137 String methodOptions = config.getParameter("method","deflate");
138 LOG.debug("Method requested: {}",methodOptions);
139
140 method = new DeflateCompressionMethod();
141 }
142
143 @Override
144 public String toString()
145 {
146 return String.format("%s[method=%s]",this.getClass().getSimpleName(),method);
147 }
148 }