1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.client;
15
16 import java.io.IOException;
17 import java.nio.channels.SelectionKey;
18 import java.nio.channels.SocketChannel;
19
20 import javax.net.ssl.SSLContext;
21 import javax.net.ssl.SSLEngine;
22 import javax.net.ssl.SSLSession;
23
24 import org.eclipse.jetty.http.HttpBuffers;
25 import org.eclipse.jetty.http.HttpMethods;
26 import org.eclipse.jetty.http.HttpVersions;
27 import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint;
28 import org.eclipse.jetty.io.Buffer;
29 import org.eclipse.jetty.io.Buffers;
30 import org.eclipse.jetty.io.Connection;
31 import org.eclipse.jetty.io.ThreadLocalBuffers;
32 import org.eclipse.jetty.io.nio.DirectNIOBuffer;
33 import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
34 import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
35 import org.eclipse.jetty.io.nio.SelectorManager;
36 import org.eclipse.jetty.util.component.AbstractLifeCycle;
37 import org.eclipse.jetty.util.log.Log;
38
39 class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector, Runnable
40 {
41 private final HttpClient _httpClient;
42 private SSLContext _sslContext;
43 private Buffers _sslBuffers;
44 private boolean _blockingConnect;
45
46 Manager _selectorManager=new Manager();
47
48
49
50
51 SelectConnector(HttpClient httpClient)
52 {
53 _httpClient = httpClient;
54 }
55
56
57
58
59
60 public boolean isBlockingConnect()
61 {
62 return _blockingConnect;
63 }
64
65
66
67
68
69 public void setBlockingConnect(boolean blockingConnect)
70 {
71 _blockingConnect = blockingConnect;
72 }
73
74
75 protected void doStart() throws Exception
76 {
77 super.doStart();
78
79 _selectorManager.start();
80
81 SSLEngine sslEngine=_selectorManager.newSslEngine();
82 SSLSession ssl_session=sslEngine.getSession();
83
84 ThreadLocalBuffers buffers = new ThreadLocalBuffers()
85 {
86 @Override
87 protected Buffer newBuffer(int size)
88 {
89
90 return new DirectNIOBuffer(size);
91 }
92 @Override
93 protected Buffer newHeader(int size)
94 {
95
96 return new DirectNIOBuffer(size);
97 }
98 };
99 buffers.setBufferSize(ssl_session.getApplicationBufferSize());
100 buffers.setHeaderSize(ssl_session.getPacketBufferSize());
101 _sslBuffers=buffers;
102
103 _httpClient._threadPool.dispatch(this);
104 }
105
106
107 protected void doStop() throws Exception
108 {
109 _selectorManager.stop();
110 }
111
112
113 public void startConnection( HttpDestination destination )
114 throws IOException
115 {
116 SocketChannel channel = SocketChannel.open();
117 Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
118 channel.configureBlocking( false );
119 channel.connect(address.toSocketAddress());
120 channel.socket().setSoTimeout( _httpClient._soTimeout );
121 _selectorManager.register( channel, destination );
122 }
123
124
125 public void run()
126 {
127 while (_httpClient.isRunning())
128 {
129 try
130 {
131 _selectorManager.doSelect(0);
132 }
133 catch (Exception e)
134 {
135 Log.warn(e.toString());
136 Log.debug(e);
137 Thread.yield();
138 }
139 }
140 }
141
142
143 class Manager extends SelectorManager
144 {
145 protected SocketChannel acceptChannel(SelectionKey key) throws IOException
146 {
147 throw new IllegalStateException();
148 }
149
150 public boolean dispatch(Runnable task)
151 {
152 return SelectConnector.this._httpClient._threadPool.dispatch(task);
153 }
154
155 protected void endPointOpened(SelectChannelEndPoint endpoint)
156 {
157 }
158
159 protected void endPointClosed(SelectChannelEndPoint endpoint)
160 {
161 }
162
163 protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint)
164 {
165 return new HttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
166 }
167
168 protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
169 {
170
171 HttpDestination dest=(HttpDestination)key.attachment();
172
173
174 SelectChannelEndPoint ep=null;
175
176 if (dest.isSecure())
177 {
178 if (dest.isProxied())
179 {
180 String connect = HttpMethods.CONNECT+" "+dest.getAddress()+HttpVersions.HTTP_1_0+"\r\n\r\n";
181
182
183 throw new IllegalStateException("Not Implemented");
184 }
185
186 SSLEngine engine=newSslEngine();
187 ep = new SslSelectChannelEndPoint(_sslBuffers,channel,selectSet,key,engine);
188 }
189 else
190 {
191 ep=new SelectChannelEndPoint(channel,selectSet,key);
192 }
193
194 HttpConnection connection=(HttpConnection)ep.getConnection();
195 connection.setDestination(dest);
196 dest.onNewConnection(connection);
197 return ep;
198 }
199
200 private synchronized SSLEngine newSslEngine() throws IOException
201 {
202 if (_sslContext==null)
203 {
204 _sslContext = SelectConnector.this._httpClient.getSSLContext();
205 }
206
207 SSLEngine sslEngine = _sslContext.createSSLEngine();
208 sslEngine.setUseClientMode(true);
209 sslEngine.beginHandshake();
210
211 return sslEngine;
212 }
213
214
215
216
217
218 protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
219 {
220 if (attachment instanceof HttpDestination)
221 ((HttpDestination)attachment).onConnectionFailed(ex);
222 else
223 super.connectionFailed(channel,ex,attachment);
224 }
225 }
226 }