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 public Connection handle() throws IOException
49 {
50 Connection connection = this;
51 boolean some_progress=false;
52 boolean progress=true;
53
54 try
55 {
56 setCurrentConnection(this);
57
58
59 while (progress && connection==this)
60 {
61 progress=false;
62 try
63 {
64
65 if (_request._async.isAsync() && !_request._async.isComplete())
66 handleRequest();
67
68 else if (!_parser.isComplete() && _parser.parseAvailable())
69 progress=true;
70
71
72 if (_generator.isCommitted() && !_generator.isComplete() && !_endp.isOutputShutdown())
73 if (_generator.flushBuffer()>0)
74 progress=true;
75
76
77 _endp.flush();
78
79
80 if (_asyncEndp.hasProgressed())
81 progress=true;
82 }
83 catch (HttpException e)
84 {
85 if (LOG.isDebugEnabled())
86 {
87 LOG.debug("uri="+_uri);
88 LOG.debug("fields="+_requestFields);
89 LOG.debug(e);
90 }
91 progress=true;
92 _generator.sendError(e.getStatus(), e.getReason(), null, true);
93 }
94 finally
95 {
96 some_progress|=progress;
97
98 if (_parser.isComplete() && _generator.isComplete())
99 {
100
101 progress=true;
102
103
104 if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
105 {
106 Connection switched=(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
107 if (switched!=null)
108 connection=switched;
109 }
110
111 reset();
112
113
114 if (!_generator.isPersistent() && !_endp.isOutputShutdown())
115 {
116 LOG.warn("Safety net oshut!!! IF YOU SEE THIS, PLEASE RAISE BUGZILLA");
117 _endp.shutdownOutput();
118 }
119 }
120 else if (_request.getAsyncContinuation().isAsyncStarted())
121 {
122
123 LOG.debug("suspended {}",this);
124
125 break;
126 }
127 }
128 }
129 }
130 finally
131 {
132 setCurrentConnection(null);
133 if (!_request.isAsyncStarted())
134 {
135 _parser.returnBuffers();
136 _generator.returnBuffers();
137 }
138
139
140 if (some_progress)
141 _total_no_progress=0;
142 else
143 {
144 _total_no_progress++;
145 if (NO_PROGRESS_INFO>0 && _total_no_progress%NO_PROGRESS_INFO==0 && (NO_PROGRESS_CLOSE<=0 || _total_no_progress< NO_PROGRESS_CLOSE))
146 LOG.info("EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this);
147 if (NO_PROGRESS_CLOSE>0 && _total_no_progress==NO_PROGRESS_CLOSE)
148 {
149 LOG.warn("Closing EndPoint making no progress: "+_total_no_progress+" "+_endp+" "+this);
150 if (_endp instanceof SelectChannelEndPoint)
151 ((SelectChannelEndPoint)_endp).getChannel().close();
152 }
153 }
154 }
155 return connection;
156 }
157
158 public void onInputShutdown() throws IOException
159 {
160
161 if (_generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
162 {
163
164 _endp.close();
165 }
166 }
167
168 }