1
18
19 package io.undertow.server;
20
21 import io.undertow.UndertowLogger;
22 import io.undertow.UndertowMessages;
23 import org.xnio.ChannelListener;
24 import org.xnio.ChannelListeners;
25 import org.xnio.Option;
26 import org.xnio.OptionMap;
27 import io.undertow.connector.ByteBufferPool;
28 import io.undertow.connector.PooledByteBuffer;
29 import org.xnio.Pool;
30 import org.xnio.StreamConnection;
31 import org.xnio.XnioIoThread;
32 import org.xnio.XnioWorker;
33 import org.xnio.conduits.ConduitStreamSinkChannel;
34 import org.xnio.conduits.ConduitStreamSourceChannel;
35 import org.xnio.conduits.StreamSinkConduit;
36 import org.xnio.conduits.StreamSourceConduit;
37
38 import java.io.IOException;
39 import java.net.SocketAddress;
40 import java.nio.ByteBuffer;
41 import java.util.LinkedList;
42 import java.util.List;
43
44 public abstract class AbstractServerConnection extends ServerConnection {
45 protected final StreamConnection channel;
46 protected final CloseSetter closeSetter;
47 protected final ByteBufferPool bufferPool;
48 protected final HttpHandler rootHandler;
49 protected final OptionMap undertowOptions;
50 protected final StreamSourceConduit originalSourceConduit;
51 protected final StreamSinkConduit originalSinkConduit;
52 protected final List<CloseListener> closeListeners = new LinkedList<>();
53
54 protected HttpServerExchange current;
55
56 private final int bufferSize;
57
58 private XnioBufferPoolAdaptor poolAdaptor;
59
60
63 protected PooledByteBuffer extraBytes;
64
65 public AbstractServerConnection(StreamConnection channel, final ByteBufferPool bufferPool, final HttpHandler rootHandler, final OptionMap undertowOptions, final int bufferSize) {
66 this.channel = channel;
67 this.bufferPool = bufferPool;
68 this.rootHandler = rootHandler;
69 this.undertowOptions = undertowOptions;
70 this.bufferSize = bufferSize;
71 closeSetter = new CloseSetter();
72 if (channel != null) {
73 this.originalSinkConduit = channel.getSinkChannel().getConduit();
74 this.originalSourceConduit = channel.getSourceChannel().getConduit();
75 channel.setCloseListener(closeSetter);
76 } else {
77 this.originalSinkConduit = null;
78 this.originalSourceConduit = null;
79 }
80 }
81
82 @Override
83 public Pool<ByteBuffer> getBufferPool() {
84 if(poolAdaptor == null) {
85 poolAdaptor = new XnioBufferPoolAdaptor(getByteBufferPool());
86 }
87 return poolAdaptor;
88 }
89
90
95 public HttpHandler getRootHandler() {
96 return rootHandler;
97 }
98
99
104 @Override
105 public ByteBufferPool getByteBufferPool() {
106 return bufferPool;
107 }
108
109
114 public StreamConnection getChannel() {
115 return channel;
116 }
117
118 @Override
119 public ChannelListener.Setter<ServerConnection> getCloseSetter() {
120 return closeSetter;
121 }
122
123 @Override
124 public XnioWorker getWorker() {
125 return channel.getWorker();
126 }
127
128 @Override
129 public XnioIoThread getIoThread() {
130 if(channel == null) {
131 return null;
132 }
133 return channel.getIoThread();
134 }
135
136
137 @Override
138 public boolean isOpen() {
139 return channel.isOpen();
140 }
141
142 @Override
143 public boolean supportsOption(final Option<?> option) {
144 return channel.supportsOption(option);
145 }
146
147 @Override
148 public <T> T getOption(final Option<T> option) throws IOException {
149 return channel.getOption(option);
150 }
151
152 @Override
153 public <T> T setOption(final Option<T> option, final T value) throws IllegalArgumentException, IOException {
154 return channel.setOption(option, value);
155 }
156
157 @Override
158 public void close() throws IOException {
159 channel.close();
160 }
161
162 @Override
163 public SocketAddress getPeerAddress() {
164 return channel.getPeerAddress();
165 }
166
167 @Override
168 public <A extends SocketAddress> A getPeerAddress(final Class<A> type) {
169 return channel.getPeerAddress(type);
170 }
171
172 @Override
173 public SocketAddress getLocalAddress() {
174 return channel.getLocalAddress();
175 }
176
177 @Override
178 public <A extends SocketAddress> A getLocalAddress(final Class<A> type) {
179 return channel.getLocalAddress(type);
180 }
181
182 @Override
183 public OptionMap getUndertowOptions() {
184 return undertowOptions;
185 }
186
187
190 @Override
191 public int getBufferSize() {
192 return bufferSize;
193 }
194
195 public PooledByteBuffer getExtraBytes() {
196 if(extraBytes != null && !extraBytes.getBuffer().hasRemaining()) {
197 extraBytes.close();
198 extraBytes = null;
199 return null;
200 }
201 return extraBytes;
202 }
203
204 public void setExtraBytes(final PooledByteBuffer extraBytes) {
205 this.extraBytes = extraBytes;
206 }
207
208
211 public StreamSourceConduit getOriginalSourceConduit() {
212 return originalSourceConduit;
213 }
214
215
218 public StreamSinkConduit getOriginalSinkConduit() {
219 return originalSinkConduit;
220 }
221
222
229 public ConduitState resetChannel() {
230 ConduitState ret = new ConduitState(channel.getSinkChannel().getConduit(), channel.getSourceChannel().getConduit());
231 channel.getSinkChannel().setConduit(originalSinkConduit);
232 channel.getSourceChannel().setConduit(originalSourceConduit);
233 return ret;
234 }
235
236
240 public void clearChannel() {
241 channel.getSinkChannel().setConduit(originalSinkConduit);
242 channel.getSourceChannel().setConduit(originalSourceConduit);
243 }
244
250 public void restoreChannel(final ConduitState state) {
251 channel.getSinkChannel().setConduit(state.sink);
252 channel.getSourceChannel().setConduit(state.source);
253 }
254
255 public static class ConduitState {
256 final StreamSinkConduit sink;
257 final StreamSourceConduit source;
258
259 private ConduitState(final StreamSinkConduit sink, final StreamSourceConduit source) {
260 this.sink = sink;
261 this.source = source;
262 }
263 }
264
265 protected static StreamSinkConduit sink(ConduitState state) {
266 return state.sink;
267 }
268
269 protected static StreamSourceConduit source(ConduitState state) {
270 return state.source;
271 }
272
273 @Override
274 public void addCloseListener(CloseListener listener) {
275 this.closeListeners.add(listener);
276 }
277
278 @Override
279 protected ConduitStreamSinkChannel getSinkChannel() {
280 return channel.getSinkChannel();
281 }
282
283 @Override
284 protected ConduitStreamSourceChannel getSourceChannel() {
285 return channel.getSourceChannel();
286 }
287
288 protected void setUpgradeListener(HttpUpgradeListener upgradeListener) {
289 throw UndertowMessages.MESSAGES.upgradeNotSupported();
290 }
291
292 @Override
293 protected void maxEntitySizeUpdated(HttpServerExchange exchange) {
294 }
295
296 private class CloseSetter implements ChannelListener.Setter<ServerConnection>, ChannelListener<StreamConnection> {
297
298 private ChannelListener<? super ServerConnection> listener;
299
300 @Override
301 public void set(ChannelListener<? super ServerConnection> listener) {
302 this.listener = listener;
303 }
304
305 @Override
306 public void handleEvent(StreamConnection channel) {
307 try {
308 for (CloseListener l : closeListeners) {
309 try {
310 l.closed(AbstractServerConnection.this);
311 } catch (Throwable e) {
312 UndertowLogger.REQUEST_LOGGER.exceptionInvokingCloseListener(l, e);
313 }
314 }
315 if (current != null) {
316 current.endExchange();
317 }
318 ChannelListeners.invokeChannelListener(AbstractServerConnection.this, listener);
319 } finally {
320 if(extraBytes != null) {
321 extraBytes.close();
322 extraBytes = null;
323 }
324 }
325 }
326 }
327 }
328