1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.bio;
16
17 import java.io.IOException;
18 import java.net.InetAddress;
19 import java.net.ServerSocket;
20 import java.net.Socket;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Set;
24
25 import org.mortbay.io.Buffer;
26 import org.mortbay.io.ByteArrayBuffer;
27 import org.mortbay.io.EndPoint;
28 import org.mortbay.io.bio.SocketEndPoint;
29 import org.mortbay.jetty.AbstractConnector;
30 import org.mortbay.jetty.EofException;
31 import org.mortbay.jetty.HttpConnection;
32 import org.mortbay.jetty.HttpException;
33 import org.mortbay.jetty.Request;
34 import org.mortbay.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 Set _connections;
53
54
55
56
57
58 public SocketConnector()
59 {
60 }
61
62
63 public Object getConnection()
64 {
65 return _serverSocket;
66 }
67
68
69 public void open() throws IOException
70 {
71
72 if (_serverSocket==null || _serverSocket.isClosed())
73 _serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
74 _serverSocket.setReuseAddress(getReuseAddress());
75 }
76
77
78 protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
79 {
80 ServerSocket ss= host==null?
81 new ServerSocket(port,backlog):
82 new ServerSocket(port,backlog,InetAddress.getByName(host));
83
84 return ss;
85 }
86
87
88 public void close() throws IOException
89 {
90 if (_serverSocket!=null)
91 _serverSocket.close();
92 _serverSocket=null;
93 }
94
95
96 public void accept(int acceptorID)
97 throws IOException, InterruptedException
98 {
99 Socket socket = _serverSocket.accept();
100 configure(socket);
101
102 Connection connection=new Connection(socket);
103 connection.dispatch();
104 }
105
106
107
108
109
110 protected HttpConnection newHttpConnection(EndPoint endpoint)
111 {
112 return new HttpConnection(this, endpoint, getServer());
113 }
114
115
116 protected Buffer newBuffer(int size)
117 {
118 return new ByteArrayBuffer(size);
119 }
120
121
122 public void customize(EndPoint endpoint, Request request)
123 throws IOException
124 {
125 Connection connection = (Connection)endpoint;
126 if (connection._sotimeout!=_maxIdleTime)
127 {
128 connection._sotimeout=_maxIdleTime;
129 ((Socket)endpoint.getTransport()).setSoTimeout(_maxIdleTime);
130 }
131
132 super.customize(endpoint, request);
133 }
134
135
136 public int getLocalPort()
137 {
138 if (_serverSocket==null || _serverSocket.isClosed())
139 return -1;
140 return _serverSocket.getLocalPort();
141 }
142
143
144 protected void doStart() throws Exception
145 {
146 _connections=new HashSet();
147 super.doStart();
148 }
149
150
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 Connection connection = (Connection)iter.next();
165 connection.close();
166 }
167 }
168
169
170
171
172 protected class Connection extends SocketEndPoint implements Runnable
173 {
174 boolean _dispatched=false;
175 HttpConnection _connection;
176 int _sotimeout;
177 protected Socket _socket;
178
179 public Connection(Socket socket) throws IOException
180 {
181 super(socket);
182 _connection = newHttpConnection(this);
183 _sotimeout=socket.getSoTimeout();
184 _socket=socket;
185 }
186
187 public void dispatch() throws InterruptedException, IOException
188 {
189 if (getThreadPool()==null || !getThreadPool().dispatch(this))
190 {
191 Log.warn("dispatch failed for {}",_connection);
192 close();
193 }
194 }
195
196 public int fill(Buffer buffer) throws IOException
197 {
198 int l = super.fill(buffer);
199 if (l<0)
200 close();
201 return l;
202 }
203
204 public void run()
205 {
206 try
207 {
208 connectionOpened(_connection);
209 synchronized(_connections)
210 {
211 _connections.add(this);
212 }
213
214 while (isStarted() && !isClosed())
215 {
216 if (_connection.isIdle())
217 {
218 if (getServer().getThreadPool().isLowOnThreads())
219 {
220 int lrmit = getLowResourceMaxIdleTime();
221 if (lrmit>=0 && _sotimeout!= lrmit)
222 {
223 _sotimeout=lrmit;
224 _socket.setSoTimeout(_sotimeout);
225 }
226 }
227 }
228 _connection.handle();
229 }
230 }
231 catch (EofException e)
232 {
233 Log.debug("EOF", e);
234 try{close();}
235 catch(IOException e2){Log.ignore(e2);}
236 }
237 catch (HttpException e)
238 {
239 Log.debug("BAD", e);
240 try{close();}
241 catch(IOException e2){Log.ignore(e2);}
242 }
243 catch(Throwable e)
244 {
245 Log.warn("handle failed",e);
246 try{close();}
247 catch(IOException e2){Log.ignore(e2);}
248 }
249 finally
250 {
251 connectionClosed(_connection);
252 synchronized(_connections)
253 {
254 _connections.remove(this);
255 }
256 }
257 }
258 }
259 }