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