1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.nio;
15
16 import java.io.IOException;
17 import java.net.InetSocketAddress;
18 import java.net.Socket;
19 import java.nio.channels.SelectionKey;
20 import java.nio.channels.ServerSocketChannel;
21 import java.nio.channels.SocketChannel;
22 import java.util.Arrays;
23 import java.util.Collections;
24
25 import org.eclipse.jetty.continuation.Continuation;
26 import org.eclipse.jetty.io.ConnectedEndPoint;
27 import org.eclipse.jetty.io.Connection;
28 import org.eclipse.jetty.io.EndPoint;
29 import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
30 import org.eclipse.jetty.io.nio.SelectorManager;
31 import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
32 import org.eclipse.jetty.server.HttpConnection;
33 import org.eclipse.jetty.server.Request;
34 import org.eclipse.jetty.util.component.AggregateLifeCycle;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.thread.Timeout.Task;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class SelectChannelConnector extends AbstractNIOConnector
65 {
66 protected ServerSocketChannel _acceptChannel;
67 private int _lowResourcesConnections;
68 private int _lowResourcesMaxIdleTime;
69 private int _localPort=-1;
70
71 private final SelectorManager _manager = new ConnectorSelectorManager();
72
73
74
75
76
77
78 public SelectChannelConnector()
79 {
80 _manager.setMaxIdleTime(getMaxIdleTime());
81 }
82
83
84 @Override
85 public void accept(int acceptorID) throws IOException
86 {
87 _manager.doSelect(acceptorID);
88 }
89
90
91 public void close() throws IOException
92 {
93 synchronized(this)
94 {
95 if(_manager.isRunning())
96 {
97 try
98 {
99 _manager.stop();
100 }
101 catch (Exception e)
102 {
103 Log.warn(e);
104 }
105 }
106 if (_acceptChannel != null)
107 _acceptChannel.close();
108 _acceptChannel = null;
109 _localPort=-2;
110 }
111 }
112
113
114 @Override
115 public void customize(EndPoint endpoint, Request request) throws IOException
116 {
117 SelectChannelEndPoint cep = ((SelectChannelEndPoint)endpoint);
118 cep.cancelIdle();
119 request.setTimeStamp(cep.getSelectSet().getNow());
120 endpoint.setMaxIdleTime(_maxIdleTime);
121 super.customize(endpoint, request);
122 }
123
124
125 @Override
126 public void persist(EndPoint endpoint) throws IOException
127 {
128 ((SelectChannelEndPoint)endpoint).scheduleIdle();
129 super.persist(endpoint);
130 }
131
132
133 public Object getConnection()
134 {
135 return _acceptChannel;
136 }
137
138
139 public int getLocalPort()
140 {
141 synchronized(this)
142 {
143 return _localPort;
144 }
145 }
146
147
148 public void open() throws IOException
149 {
150 synchronized(this)
151 {
152 if (_acceptChannel == null)
153 {
154
155 _acceptChannel = ServerSocketChannel.open();
156
157 _acceptChannel.configureBlocking(true);
158
159
160 _acceptChannel.socket().setReuseAddress(getReuseAddress());
161 InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
162 _acceptChannel.socket().bind(addr,getAcceptQueueSize());
163
164 _localPort=_acceptChannel.socket().getLocalPort();
165 if (_localPort<=0)
166 throw new IOException("Server channel not bound");
167
168 }
169 }
170 }
171
172
173 @Override
174 public void setMaxIdleTime(int maxIdleTime)
175 {
176 _manager.setMaxIdleTime(maxIdleTime);
177 super.setMaxIdleTime(maxIdleTime);
178 }
179
180
181
182
183
184 public int getLowResourcesConnections()
185 {
186 return _lowResourcesConnections;
187 }
188
189
190
191
192
193
194
195
196 public void setLowResourcesConnections(int lowResourcesConnections)
197 {
198 _lowResourcesConnections=lowResourcesConnections;
199 }
200
201
202
203
204
205 @Override
206 public int getLowResourcesMaxIdleTime()
207 {
208 return _lowResourcesMaxIdleTime;
209 }
210
211
212
213
214
215
216
217
218
219 @Override
220 public void setLowResourcesMaxIdleTime(int lowResourcesMaxIdleTime)
221 {
222 _lowResourcesMaxIdleTime=lowResourcesMaxIdleTime;
223 super.setLowResourcesMaxIdleTime(lowResourcesMaxIdleTime);
224 }
225
226
227
228
229
230
231 @Override
232 protected void doStart() throws Exception
233 {
234 _manager.setSelectSets(getAcceptors());
235 _manager.setMaxIdleTime(getMaxIdleTime());
236 _manager.setLowResourcesConnections(getLowResourcesConnections());
237 _manager.setLowResourcesMaxIdleTime(getLowResourcesMaxIdleTime());
238 _manager.start();
239
240 super.doStart();
241
242
243 _manager.dispatch(new Runnable()
244 {
245 public void run()
246 {
247 final ServerSocketChannel server=_acceptChannel;
248 while (isRunning() && _acceptChannel==server && server.isOpen())
249 {
250 try
251 {
252 SocketChannel channel = server.accept();
253 channel.configureBlocking(false);
254 Socket socket = channel.socket();
255 configure(socket);
256 _manager.register(channel);
257 }
258 catch(IOException e)
259 {
260 Log.ignore(e);
261 }
262 }
263 }
264 });
265
266 }
267
268
269
270
271
272 @Override
273 protected void doStop() throws Exception
274 {
275 super.doStop();
276 }
277
278
279 protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
280 {
281 return new SelectChannelEndPoint(channel,selectSet,key, SelectChannelConnector.this._maxIdleTime);
282 }
283
284
285 protected Connection newConnection(SocketChannel channel,final SelectChannelEndPoint endpoint)
286 {
287 return new HttpConnection(SelectChannelConnector.this,endpoint,getServer())
288 {
289
290 @Override
291 public void cancelTimeout(Task task)
292 {
293 endpoint.getSelectSet().cancelTimeout(task);
294 }
295
296
297 @Override
298 public void scheduleTimeout(Task task, long timeoutMs)
299 {
300 endpoint.getSelectSet().scheduleTimeout(task,timeoutMs);
301 }
302 };
303 }
304
305
306 public void dump(Appendable out, String indent) throws IOException
307 {
308 out.append(String.valueOf(this)).append("\n");
309 AggregateLifeCycle.dump(out,indent,Arrays.asList(new Object[]{_acceptChannel,_acceptChannel.isOpen()?"OPEN":"CLOSED",_manager}));
310 }
311
312
313
314
315 private final class ConnectorSelectorManager extends SelectorManager
316 {
317 @Override
318 public boolean dispatch(Runnable task)
319 {
320 return getThreadPool().dispatch(task);
321 }
322
323 @Override
324 protected void endPointClosed(final SelectChannelEndPoint endpoint)
325 {
326 connectionClosed(endpoint.getConnection());
327 }
328
329 @Override
330 protected void endPointOpened(SelectChannelEndPoint endpoint)
331 {
332
333 connectionOpened(endpoint.getConnection());
334 }
335
336 @Override
337 protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
338 {
339 connectionUpgraded(oldConnection,endpoint.getConnection());
340 }
341
342 @Override
343 protected Connection newConnection(SocketChannel channel,SelectChannelEndPoint endpoint)
344 {
345 return SelectChannelConnector.this.newConnection(channel,endpoint);
346 }
347
348 @Override
349 protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey sKey) throws IOException
350 {
351 return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);
352 }
353 }
354
355 }