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.ByteChannel;
20 import java.nio.channels.ServerSocketChannel;
21 import java.nio.channels.SocketChannel;
22
23 import org.eclipse.jetty.http.HttpException;
24 import org.eclipse.jetty.io.EndPoint;
25 import org.eclipse.jetty.io.EofException;
26 import org.eclipse.jetty.io.nio.ChannelEndPoint;
27 import org.eclipse.jetty.server.HttpConnection;
28 import org.eclipse.jetty.server.Request;
29 import org.eclipse.jetty.util.log.Log;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class BlockingChannelConnector extends AbstractNIOConnector
45 {
46 private transient ServerSocketChannel _acceptChannel;
47
48
49
50
51
52 public BlockingChannelConnector()
53 {
54 }
55
56
57 public Object getConnection()
58 {
59 return _acceptChannel;
60 }
61
62
63 public void open() throws IOException
64 {
65
66 _acceptChannel= ServerSocketChannel.open();
67 _acceptChannel.configureBlocking(true);
68
69
70 InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
71 _acceptChannel.socket().bind(addr,getAcceptQueueSize());
72 }
73
74
75 public void close() throws IOException
76 {
77 if (_acceptChannel != null)
78 _acceptChannel.close();
79 _acceptChannel=null;
80 }
81
82
83 public void accept(int acceptorID)
84 throws IOException, InterruptedException
85 {
86 SocketChannel channel = _acceptChannel.accept();
87 channel.configureBlocking(true);
88 Socket socket=channel.socket();
89 configure(socket);
90
91 Connection connection=new Connection(channel);
92 connection.dispatch();
93 }
94
95
96 public void customize(EndPoint endpoint, Request request)
97 throws IOException
98 {
99 Connection connection = (Connection)endpoint;
100 if (connection._sotimeout!=_maxIdleTime)
101 {
102 connection._sotimeout=_maxIdleTime;
103 ((SocketChannel)endpoint.getTransport()).socket().setSoTimeout(_maxIdleTime);
104 }
105
106 super.customize(endpoint, request);
107 configure(((SocketChannel)endpoint.getTransport()).socket());
108 }
109
110
111
112 public int getLocalPort()
113 {
114 if (_acceptChannel==null || !_acceptChannel.isOpen())
115 return -1;
116 return _acceptChannel.socket().getLocalPort();
117 }
118
119
120
121
122 private class Connection extends ChannelEndPoint implements Runnable
123 {
124 final HttpConnection _connection;
125 boolean _dispatched=false;
126 int _sotimeout;
127
128 Connection(ByteChannel channel)
129 {
130 super(channel);
131 _connection = new HttpConnection(BlockingChannelConnector.this,this,getServer());
132 }
133
134 void dispatch() throws IOException
135 {
136 if (!getThreadPool().dispatch(this))
137 {
138 Log.warn("dispatch failed for {}",_connection);
139 Connection.this.close();
140 }
141 }
142
143 public void run()
144 {
145 try
146 {
147 connectionOpened(_connection);
148
149 while (isOpen())
150 {
151 if (_connection.isIdle())
152 {
153 if (getServer().getThreadPool().isLowOnThreads())
154 {
155 int lrmit = getLowResourceMaxIdleTime();
156 if (lrmit>=0 && _sotimeout!= lrmit)
157 {
158 _sotimeout=lrmit;
159 ((SocketChannel)getTransport()).socket().setSoTimeout(_sotimeout);
160 }
161 }
162 }
163 _connection.handle();
164 }
165 }
166 catch (EofException e)
167 {
168 Log.debug("EOF", e);
169 try{Connection.this.close();}
170 catch(IOException e2){Log.ignore(e2);}
171 }
172 catch (HttpException e)
173 {
174 Log.debug("BAD", e);
175 try{Connection.this.close();}
176 catch(IOException e2){Log.ignore(e2);}
177 }
178 catch(Throwable e)
179 {
180 Log.warn("handle failed",e);
181 try{Connection.this.close();}
182 catch(IOException e2){Log.ignore(e2);}
183 }
184 finally
185 {
186 connectionClosed(_connection);
187 }
188 }
189 }
190 }