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.net.SocketException;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Set;
24
25 import org.eclipse.jetty.http.HttpException;
26 import org.eclipse.jetty.io.Buffer;
27 import org.eclipse.jetty.io.ConnectedEndPoint;
28 import org.eclipse.jetty.io.Connection;
29 import org.eclipse.jetty.io.EndPoint;
30 import org.eclipse.jetty.io.EofException;
31 import org.eclipse.jetty.io.bio.SocketEndPoint;
32 import org.eclipse.jetty.server.AbstractConnector;
33 import org.eclipse.jetty.server.BlockingHttpConnection;
34 import org.eclipse.jetty.server.HttpConnection;
35 import org.eclipse.jetty.server.Request;
36 import org.eclipse.jetty.util.log.Log;
37 import org.eclipse.jetty.util.log.Logger;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class SocketConnector extends AbstractConnector
53 {
54 private static final Logger LOG = Log.getLogger(SocketConnector.class);
55
56 protected ServerSocket _serverSocket;
57 protected final Set<EndPoint> _connections;
58 protected volatile int _localPort=-1;
59
60
61
62
63
64 public SocketConnector()
65 {
66 _connections=new HashSet<EndPoint>();
67 }
68
69
70 public Object getConnection()
71 {
72 return _serverSocket;
73 }
74
75
76 public void open() throws IOException
77 {
78
79 if (_serverSocket==null || _serverSocket.isClosed())
80 _serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
81 _serverSocket.setReuseAddress(getReuseAddress());
82 _localPort=_serverSocket.getLocalPort();
83 if (_localPort<=0)
84 throw new IllegalStateException("port not allocated for "+this);
85
86 }
87
88
89 protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
90 {
91 ServerSocket ss= host==null?
92 new ServerSocket(port,backlog):
93 new ServerSocket(port,backlog,InetAddress.getByName(host));
94
95 return ss;
96 }
97
98
99 public void close() throws IOException
100 {
101 if (_serverSocket!=null)
102 _serverSocket.close();
103 _serverSocket=null;
104 _localPort=-2;
105 }
106
107
108 @Override
109 public void accept(int acceptorID)
110 throws IOException, InterruptedException
111 {
112 Socket socket = _serverSocket.accept();
113 configure(socket);
114
115 ConnectorEndPoint connection=new ConnectorEndPoint(socket);
116 connection.dispatch();
117 }
118
119
120
121
122
123 protected Connection newConnection(EndPoint endpoint)
124 {
125 return new BlockingHttpConnection(this, endpoint, getServer());
126 }
127
128
129 @Override
130 public void customize(EndPoint endpoint, Request request)
131 throws IOException
132 {
133 ConnectorEndPoint connection = (ConnectorEndPoint)endpoint;
134 int lrmit = isLowResources()?_lowResourceMaxIdleTime:_maxIdleTime;
135 connection.setMaxIdleTime(lrmit);
136
137 super.customize(endpoint, request);
138 }
139
140
141 public int getLocalPort()
142 {
143 return _localPort;
144 }
145
146
147 @Override
148 protected void doStart() throws Exception
149 {
150 _connections.clear();
151 super.doStart();
152 }
153
154
155 @Override
156 protected void doStop() throws Exception
157 {
158 super.doStop();
159 Set set=null;
160
161 synchronized(_connections)
162 {
163 set= new HashSet(_connections);
164 }
165
166 Iterator iter=set.iterator();
167 while(iter.hasNext())
168 {
169 ConnectorEndPoint connection = (ConnectorEndPoint)iter.next();
170 connection.close();
171 }
172 }
173
174
175
176
177 protected class ConnectorEndPoint extends SocketEndPoint implements Runnable, ConnectedEndPoint
178 {
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 (SocketException e)
255 {
256 LOG.debug("EOF", e);
257 try{close();}
258 catch(IOException e2){LOG.ignore(e2);}
259 }
260 catch (HttpException e)
261 {
262 LOG.debug("BAD", e);
263 try{close();}
264 catch(IOException e2){LOG.ignore(e2);}
265 }
266 catch(Exception e)
267 {
268 LOG.warn("handle failed?",e);
269 try{close();}
270 catch(IOException e2){LOG.ignore(e2);}
271 }
272 finally
273 {
274 connectionClosed(_connection);
275 synchronized(_connections)
276 {
277 _connections.remove(this);
278 }
279
280
281 try
282 {
283 if (!_socket.isClosed())
284 {
285 long timestamp=System.currentTimeMillis();
286 int max_idle=getMaxIdleTime();
287
288 _socket.setSoTimeout(getMaxIdleTime());
289 int c=0;
290 do
291 {
292 c = _socket.getInputStream().read();
293 }
294 while (c>=0 && (System.currentTimeMillis()-timestamp)<max_idle);
295 if (!_socket.isClosed())
296 _socket.close();
297 }
298 }
299 catch(IOException e)
300 {
301 LOG.ignore(e);
302 }
303 }
304 }
305 }
306 }