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