1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17
18 import org.eclipse.jetty.http.HttpException;
19 import org.eclipse.jetty.http.HttpStatus;
20 import org.eclipse.jetty.io.AsyncEndPoint;
21 import org.eclipse.jetty.io.Connection;
22 import org.eclipse.jetty.io.EndPoint;
23 import org.eclipse.jetty.io.nio.AsyncConnection;
24 import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
25 import org.eclipse.jetty.util.log.Log;
26 import org.eclipse.jetty.util.log.Logger;
27
28
29
30
31
32
33 public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection
34 {
35 private final static int NO_PROGRESS_INFO = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_INFO",100);
36 private final static int NO_PROGRESS_CLOSE = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_CLOSE",200);
37
38 private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
39 private int _total_no_progress;
40 private final AsyncEndPoint _asyncEndp;
41
42 public AsyncHttpConnection(Connector connector, EndPoint endpoint, Server server)
43 {
44 super(connector,endpoint,server);
45 _asyncEndp=(AsyncEndPoint)endpoint;
46 }
47
48 @Override
49 public Connection handle() throws IOException
50 {
51 Connection connection = this;
52 boolean some_progress=false;
53 boolean progress=true;
54
55 try
56 {
57 setCurrentConnection(this);
58
59
60 _asyncEndp.setCheckForIdle(false);
61
62
63
64 while (progress && connection==this)
65 {
66 progress=false;
67 try
68 {
69
70 if (_request._async.isAsync())
71 {
72 if (_request._async.isDispatchable())
73 handleRequest();
74 }
75
76 else if (!_parser.isComplete() && _parser.parseAvailable())
77 progress=true;
78
79
80 if (_generator.isCommitted() && !_generator.isComplete() && !_endp.isOutputShutdown())
81 if (_generator.flushBuffer()>0)
82 progress=true;
83
84
85 _endp.flush();
86
87
88 if (_asyncEndp.hasProgressed())
89 progress=true;
90 }
91 catch (HttpException e)
92 {
93 if (LOG.isDebugEnabled())
94 {
95 LOG.debug("uri="+_uri);
96 LOG.debug("fields="+_requestFields);
97 LOG.debug(e);
98 }
99 progress=true;
100 _generator.sendError(e.getStatus(), e.getReason(), null, true);
101 }
102 finally
103 {
104 some_progress|=progress;
105
106 if (_parser.isComplete() && _generator.isComplete())
107 {
108
109 progress=true;
110
111
112 if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
113 {
114 Connection switched=(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
115 if (switched!=null)
116 connection=switched;
117 }
118
119 reset();
120
121
122 if (!_generator.isPersistent() && !_endp.isOutputShutdown())
123 {
124 LOG.warn("Safety net oshut!!! IF YOU SEE THIS, PLEASE RAISE BUGZILLA");
125 _endp.shutdownOutput();
126 }
127 }
128 else if (_request.getAsyncContinuation().isAsyncStarted())
129 {
130
131
132 LOG.debug("suspended {}",this);
133 progress=false;
134 }
135 }
136 }
137 }
138 finally
139 {
140 setCurrentConnection(null);
141
142
143 if (!_request.getAsyncContinuation().isAsyncStarted())
144 {
145
146 _parser.returnBuffers();
147 _generator.returnBuffers();
148
149
150 _asyncEndp.setCheckForIdle(true);
151 }
152
153
154 if (some_progress)
155 _total_no_progress=0;
156 else
157 {
158 _total_no_progress++;
159 if (NO_PROGRESS_INFO>0 && _total_no_progress%NO_PROGRESS_INFO==0 && (NO_PROGRESS_CLOSE<=0 || _total_no_progress< NO_PROGRESS_CLOSE))
160 LOG.info("EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this);
161 if (NO_PROGRESS_CLOSE>0 && _total_no_progress==NO_PROGRESS_CLOSE)
162 {
163 LOG.warn("Closing EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this);
164 if (_endp instanceof SelectChannelEndPoint)
165 ((SelectChannelEndPoint)_endp).getChannel().close();
166 }
167 }
168 }
169 return connection;
170 }
171
172 public void onInputShutdown() throws IOException
173 {
174
175 if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
176 {
177
178 _endp.close();
179 }
180 }
181
182 }