comparison src/org/eclipse/jetty/server/AsyncHttpConnection.java @ 802:3428c60d7cfc

replace jetty jars with source
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 07 Sep 2016 21:15:48 -0600
parents
children 8e9db0bbf4f9
comparison
equal deleted inserted replaced
801:6a21393191c1 802:3428c60d7cfc
1 //
2 // ========================================================================
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22
23 import org.eclipse.jetty.http.HttpException;
24 import org.eclipse.jetty.http.HttpStatus;
25 import org.eclipse.jetty.io.AsyncEndPoint;
26 import org.eclipse.jetty.io.Connection;
27 import org.eclipse.jetty.io.EndPoint;
28 import org.eclipse.jetty.io.nio.AsyncConnection;
29 import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
30 import org.eclipse.jetty.util.log.Log;
31 import org.eclipse.jetty.util.log.Logger;
32
33
34 /* ------------------------------------------------------------ */
35 /** Asychronous Server HTTP connection
36 *
37 */
38 public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection
39 {
40 private final static int NO_PROGRESS_INFO = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_INFO",100);
41 private final static int NO_PROGRESS_CLOSE = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_CLOSE",200);
42
43 private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
44 private int _total_no_progress;
45 private final AsyncEndPoint _asyncEndp;
46 private boolean _readInterested = true;
47
48 public AsyncHttpConnection(Connector connector, EndPoint endpoint, Server server)
49 {
50 super(connector,endpoint,server);
51 _asyncEndp=(AsyncEndPoint)endpoint;
52 }
53
54 @Override
55 public Connection handle() throws IOException
56 {
57 Connection connection = this;
58 boolean some_progress=false;
59 boolean progress=true;
60
61 try
62 {
63 setCurrentConnection(this);
64
65 // don't check for idle while dispatched (unless blocking IO is done).
66 _asyncEndp.setCheckForIdle(false);
67
68
69 // While progress and the connection has not changed
70 while (progress && connection==this)
71 {
72 progress=false;
73 try
74 {
75 // Handle resumed request
76 if (_request._async.isAsync())
77 {
78 if (_request._async.isDispatchable())
79 handleRequest();
80 }
81 // else Parse more input
82 else if (!_parser.isComplete() && _parser.parseAvailable())
83 progress=true;
84
85 // Generate more output
86 if (_generator.isCommitted() && !_generator.isComplete() && !_endp.isOutputShutdown() && !_request.getAsyncContinuation().isAsyncStarted())
87 if (_generator.flushBuffer()>0)
88 progress=true;
89
90 // Flush output
91 _endp.flush();
92
93 // Has any IO been done by the endpoint itself since last loop
94 if (_asyncEndp.hasProgressed())
95 progress=true;
96 }
97 catch (HttpException e)
98 {
99 if (LOG.isDebugEnabled())
100 {
101 LOG.debug("uri="+_uri);
102 LOG.debug("fields="+_requestFields);
103 LOG.debug(e);
104 }
105 progress=true;
106 _generator.sendError(e.getStatus(), e.getReason(), null, true);
107 }
108 finally
109 {
110 some_progress|=progress;
111 // Is this request/response round complete and are fully flushed?
112 boolean parserComplete = _parser.isComplete();
113 boolean generatorComplete = _generator.isComplete();
114 boolean complete = parserComplete && generatorComplete;
115 if (parserComplete)
116 {
117 if (generatorComplete)
118 {
119 // Reset the parser/generator
120 progress=true;
121
122 // look for a switched connection instance?
123 if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
124 {
125 Connection switched=(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
126 if (switched!=null)
127 connection=switched;
128 }
129
130 reset();
131
132 // TODO Is this still required?
133 if (!_generator.isPersistent() && !_endp.isOutputShutdown())
134 {
135 LOG.warn("Safety net oshut!!! IF YOU SEE THIS, PLEASE RAISE BUGZILLA");
136 _endp.shutdownOutput();
137 }
138 }
139 else
140 {
141 // We have finished parsing, but not generating so
142 // we must not be interested in reading until we
143 // have finished generating and we reset the generator
144 _readInterested = false;
145 LOG.debug("Disabled read interest while writing response {}", _endp);
146 }
147 }
148
149 if (!complete && _request.getAsyncContinuation().isAsyncStarted())
150 {
151 // The request is suspended, so even though progress has been made,
152 // exit the while loop by setting progress to false
153 LOG.debug("suspended {}",this);
154 progress=false;
155 }
156 }
157 }
158 }
159 finally
160 {
161 setCurrentConnection(null);
162
163 // If we are not suspended
164 if (!_request.getAsyncContinuation().isAsyncStarted())
165 {
166 // return buffers
167 _parser.returnBuffers();
168 _generator.returnBuffers();
169
170 // reenable idle checking unless request is suspended
171 _asyncEndp.setCheckForIdle(true);
172 }
173
174 // Safety net to catch spinning
175 if (some_progress)
176 _total_no_progress=0;
177 else
178 {
179 _total_no_progress++;
180 if (NO_PROGRESS_INFO>0 && _total_no_progress%NO_PROGRESS_INFO==0 && (NO_PROGRESS_CLOSE<=0 || _total_no_progress< NO_PROGRESS_CLOSE))
181 LOG.info("EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this);
182 if (NO_PROGRESS_CLOSE>0 && _total_no_progress==NO_PROGRESS_CLOSE)
183 {
184 LOG.warn("Closing EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this);
185 if (_endp instanceof SelectChannelEndPoint)
186 ((SelectChannelEndPoint)_endp).getChannel().close();
187 }
188 }
189 }
190 return connection;
191 }
192
193 public void onInputShutdown() throws IOException
194 {
195 // If we don't have a committed response and we are not suspended
196 if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
197 {
198 // then no more can happen, so close.
199 _endp.close();
200 }
201
202 // Make idle parser seek EOF
203 if (_parser.isIdle())
204 _parser.setPersistent(false);
205 }
206
207 @Override
208 public void reset()
209 {
210 _readInterested = true;
211 LOG.debug("Enabled read interest {}", _endp);
212 super.reset();
213 }
214
215 @Override
216 public boolean isSuspended()
217 {
218 return !_readInterested || super.isSuspended();
219 }
220 }