1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.bio;
15
16 import java.io.IOException;
17 import java.net.InetAddress;
18 import java.net.ServerSocket;
19 import java.net.Socket;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Set;
23
24 import org.eclipse.jetty.http.HttpException;
25 import org.eclipse.jetty.io.Buffer;
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.EofException;
30 import org.eclipse.jetty.io.bio.SocketEndPoint;
31 import org.eclipse.jetty.server.AbstractConnector;
32 import org.eclipse.jetty.server.BlockingHttpConnection;
33 import org.eclipse.jetty.server.HttpConnection;
34 import org.eclipse.jetty.server.Request;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class SocketConnector extends AbstractConnector
52 {
53 private static final Logger LOG = Log.getLogger(SocketConnector.class);
54
55 protected ServerSocket _serverSocket;
56 protected final Set<EndPoint> _connections;
57 protected volatile int _localPort=-1;
58
59
60
61
62
63 public SocketConnector()
64 {
65 _connections=new HashSet<EndPoint>();
66 }
67
68
69 public Object getConnection()
70 {
71 return _serverSocket;
72 }
73
74
75 public void open() throws IOException
76 {
77
78 if (_serverSocket==null || _serverSocket.isClosed())
79 _serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
80 _serverSocket.setReuseAddress(getReuseAddress());
81 _localPort=_serverSocket.getLocalPort();
82 if (_localPort<=0)
83 throw new IllegalStateException("port not allocated for "+this);
84
85 }
86
87
88 protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
89 {
90 ServerSocket ss= host==null?
91 new ServerSocket(port,backlog):
92 new ServerSocket(port,backlog,InetAddress.getByName(host));
93
94 return ss;
95 }
96
97
98 public void close() throws IOException
99 {
100 if (_serverSocket!=null)
101 _serverSocket.close();
102 _serverSocket=null;
103 _localPort=-2;
104 }
105
106
107 @Override
108 public void accept(int acceptorID)
109 throws IOException, InterruptedException
110 {
111 Socket socket = _serverSocket.accept();
112 configure(socket);
113
114 ConnectorEndPoint connection=new ConnectorEndPoint(socket);
115 connection.dispatch();
116 }
117
118
119
120
121
122 protected Connection newConnection(EndPoint endpoint)
123 {
124 return new BlockingHttpConnection(this, endpoint, getServer());
125 }
126
127
128 @Override
129 public void customize(EndPoint endpoint, Request request)
130 throws IOException
131 {
132 ConnectorEndPoint connection = (ConnectorEndPoint)endpoint;
133 int lrmit = isLowResources()?_lowResourceMaxIdleTime:_maxIdleTime;
134 connection.setMaxIdleTime(lrmit);
135
136 super.customize(endpoint, request);
137 }
138
139
140 public int getLocalPort()
141 {
142 return _localPort;
143 }
144
145
146 @Override
147 protected void doStart() throws Exception
148 {
149 _connections.clear();
150 super.doStart();
151 }
152
153
154 @Override
155 protected void doStop() throws Exception
156 {
157 super.doStop();
158 Set set=null;
159
160 synchronized(_connections)
161 {
162 set= new HashSet(_connections);
163 }
164
165 Iterator iter=set.iterator();
166 while(iter.hasNext())
167 {
168 ConnectorEndPoint connection = (ConnectorEndPoint)iter.next();
169 connection.close();
170 }
171 }
172
173
174
175
176 protected class ConnectorEndPoint extends SocketEndPoint implements Runnable, ConnectedEndPoint
177 {
178 boolean _dispatched=false;
179 volatile Connection _connection;
180 protected final Socket _socket;
181
182 public ConnectorEndPoint(Socket socket) throws IOException
183 {
184 super(socket,_maxIdleTime);
185 _connection = newConnection(this);
186 _socket=socket;
187 }
188
189 public Connection getConnection()
190 {
191 return _connection;
192 }
193
194 public void setConnection(Connection connection)
195 {
196 if (_connection!=connection)
197 connectionUpgraded(_connection,connection);
198 _connection=connection;
199 }
200
201 public void dispatch() throws IOException
202 {
203 if (getThreadPool()==null || !getThreadPool().dispatch(this))
204 {
205 LOG.warn("dispatch failed for {}",_connection);
206 close();
207 }
208 }
209
210 @Override
211 public int fill(Buffer buffer) throws IOException
212 {
213 int l = super.fill(buffer);
214 if (l<0)
215 close();
216 return l;
217 }
218
219 @Override
220 public void close() throws IOException
221 {
222 if (_connection instanceof HttpConnection)
223 ((HttpConnection)_connection).getRequest().getAsyncContinuation().cancel();
224 super.close();
225 }
226
227 public void run()
228 {
229 try
230 {
231 connectionOpened(_connection);
232 synchronized(_connections)
233 {
234 _connections.add(this);
235 }
236
237 while (isStarted() && !isClosed())
238 {
239 if (_connection.isIdle())
240 {
241 if (isLowResources())
242 setMaxIdleTime(getLowResourcesMaxIdleTime());
243 }
244
245 _connection=_connection.handle();
246 }
247 }
248 catch (EofException e)
249 {
250 LOG.debug("EOF", e);
251 try{close();}
252 catch(IOException e2){LOG.ignore(e2);}
253 }
254 catch (HttpException e)
255 {
256 LOG.debug("BAD", e);
257 try{close();}
258 catch(IOException e2){LOG.ignore(e2);}
259 }
260 catch(Exception e)
261 {
262 LOG.warn("handle failed?",e);
263 try{close();}
264 catch(IOException e2){LOG.ignore(e2);}
265 }
266 finally
267 {
268 connectionClosed(_connection);
269 synchronized(_connections)
270 {
271 _connections.remove(this);
272 }
273
274
275 try
276 {
277 if (!_socket.isClosed())
278 {
279 long timestamp=System.currentTimeMillis();
280 int max_idle=getMaxIdleTime();
281
282 _socket.setSoTimeout(getMaxIdleTime());
283 int c=0;
284 do
285 {
286 c = _socket.getInputStream().read();
287 }
288 while (c>=0 && (System.currentTimeMillis()-timestamp)<max_idle);
289 if (!_socket.isClosed())
290 _socket.close();
291 }
292 }
293 catch(IOException e)
294 {
295 LOG.ignore(e);
296 }
297 }
298 }
299 }
300 }