Mercurial Hosting > luan
comparison src/org/eclipse/jetty/io/nio/SslConnection.java @ 940:b77d631b9e28
remove scheduleTimeout() and cancelTimeout()
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 11 Oct 2016 00:13:30 -0600 |
parents | 8e9db0bbf4f9 |
children | 89fe80dfab2c |
comparison
equal
deleted
inserted
replaced
939:8db5996c8c89 | 940:b77d631b9e28 |
---|---|
32 import org.eclipse.jetty.io.Buffer; | 32 import org.eclipse.jetty.io.Buffer; |
33 import org.eclipse.jetty.io.Connection; | 33 import org.eclipse.jetty.io.Connection; |
34 import org.eclipse.jetty.io.EndPoint; | 34 import org.eclipse.jetty.io.EndPoint; |
35 import org.slf4j.Logger; | 35 import org.slf4j.Logger; |
36 import org.slf4j.LoggerFactory; | 36 import org.slf4j.LoggerFactory; |
37 import org.eclipse.jetty.util.thread.Timeout.Task; | 37 |
38 | 38 |
39 /* ------------------------------------------------------------ */ | 39 /* ------------------------------------------------------------ */ |
40 /** SSL Connection. | 40 /** SSL Connection. |
41 * An AysyncConnection that acts as an interceptor between and EndPoint and another | 41 * An AysyncConnection that acts as an interceptor between and EndPoint and another |
42 * Connection, that implements TLS encryption using an {@link SSLEngine}. | 42 * Connection, that implements TLS encryption using an {@link SSLEngine}. |
45 * it's source/sink of encrypted data. It then provides {@link #getSslEndPoint()} to | 45 * it's source/sink of encrypted data. It then provides {@link #getSslEndPoint()} to |
46 * expose a source/sink of unencrypted data to another connection (eg HttpConnection). | 46 * expose a source/sink of unencrypted data to another connection (eg HttpConnection). |
47 */ | 47 */ |
48 public class SslConnection extends AbstractConnection implements AsyncConnection | 48 public class SslConnection extends AbstractConnection implements AsyncConnection |
49 { | 49 { |
50 private final Logger _logger = LoggerFactory.getLogger("org.eclipse.jetty.io.nio.ssl"); | 50 private final Logger _logger = LoggerFactory.getLogger("org.eclipse.jetty.io.nio.ssl"); |
51 | 51 |
52 private static final NIOBuffer __ZERO_BUFFER=new IndirectNIOBuffer(0); | 52 private static final NIOBuffer __ZERO_BUFFER=new IndirectNIOBuffer(0); |
53 | 53 |
54 private static final ThreadLocal<SslBuffers> __buffers = new ThreadLocal<SslBuffers>(); | 54 private static final ThreadLocal<SslBuffers> __buffers = new ThreadLocal<SslBuffers>(); |
55 private final SSLEngine _engine; | 55 private final SSLEngine _engine; |
56 private final SSLSession _session; | 56 private final SSLSession _session; |
57 private AsyncConnection _connection; | 57 private AsyncConnection _connection; |
58 private final SslEndPoint _sslEndPoint; | 58 private final SslEndPoint _sslEndPoint; |
59 private int _allocations; | 59 private int _allocations; |
60 private SslBuffers _buffers; | 60 private SslBuffers _buffers; |
61 private NIOBuffer _inbound; | 61 private NIOBuffer _inbound; |
62 private NIOBuffer _unwrapBuf; | 62 private NIOBuffer _unwrapBuf; |
63 private NIOBuffer _outbound; | 63 private NIOBuffer _outbound; |
64 private AsyncEndPoint _aEndp; | 64 private AsyncEndPoint _aEndp; |
65 private boolean _allowRenegotiate=true; | 65 private boolean _allowRenegotiate=true; |
66 private boolean _handshook; | 66 private boolean _handshook; |
67 private boolean _ishut; | 67 private boolean _ishut; |
68 private boolean _oshut; | 68 private boolean _oshut; |
69 private final AtomicBoolean _progressed = new AtomicBoolean(); | 69 private final AtomicBoolean _progressed = new AtomicBoolean(); |
70 | 70 |
71 /* ------------------------------------------------------------ */ | 71 /* ------------------------------------------------------------ */ |
72 /* this is a half baked buffer pool | 72 /* this is a half baked buffer pool |
73 */ | 73 */ |
74 private static class SslBuffers | 74 private static class SslBuffers |
75 { | 75 { |
76 final NIOBuffer _in; | 76 final NIOBuffer _in; |
77 final NIOBuffer _out; | 77 final NIOBuffer _out; |
78 final NIOBuffer _unwrap; | 78 final NIOBuffer _unwrap; |
79 | 79 |
80 SslBuffers(int packetSize, int appSize) | 80 SslBuffers(int packetSize, int appSize) |
81 { | 81 { |
82 _in=new IndirectNIOBuffer(packetSize); | 82 _in=new IndirectNIOBuffer(packetSize); |
83 _out=new IndirectNIOBuffer(packetSize); | 83 _out=new IndirectNIOBuffer(packetSize); |
84 _unwrap=new IndirectNIOBuffer(appSize); | 84 _unwrap=new IndirectNIOBuffer(appSize); |
85 } | 85 } |
86 } | 86 } |
87 | 87 |
88 /* ------------------------------------------------------------ */ | 88 /* ------------------------------------------------------------ */ |
89 public SslConnection(SSLEngine engine,EndPoint endp) | 89 public SslConnection(SSLEngine engine,EndPoint endp) |
90 { | 90 { |
91 this(engine,endp,System.currentTimeMillis()); | 91 this(engine,endp,System.currentTimeMillis()); |
92 } | 92 } |
93 | 93 |
94 /* ------------------------------------------------------------ */ | 94 /* ------------------------------------------------------------ */ |
95 public SslConnection(SSLEngine engine,EndPoint endp, long timeStamp) | 95 public SslConnection(SSLEngine engine,EndPoint endp, long timeStamp) |
96 { | 96 { |
97 super(endp,timeStamp); | 97 super(endp,timeStamp); |
98 _engine=engine; | 98 _engine=engine; |
99 _session=_engine.getSession(); | 99 _session=_engine.getSession(); |
100 _aEndp=(AsyncEndPoint)endp; | 100 _aEndp=(AsyncEndPoint)endp; |
101 _sslEndPoint = newSslEndPoint(); | 101 _sslEndPoint = newSslEndPoint(); |
102 } | 102 } |
103 | 103 |
104 /* ------------------------------------------------------------ */ | 104 /* ------------------------------------------------------------ */ |
105 protected SslEndPoint newSslEndPoint() | 105 protected SslEndPoint newSslEndPoint() |
106 { | 106 { |
107 return new SslEndPoint(); | 107 return new SslEndPoint(); |
108 } | 108 } |
109 | 109 |
110 /* ------------------------------------------------------------ */ | 110 /* ------------------------------------------------------------ */ |
111 /** | 111 /** |
112 * @return True if SSL re-negotiation is allowed (default false) | 112 * @return True if SSL re-negotiation is allowed (default false) |
113 */ | 113 */ |
114 public boolean isAllowRenegotiate() | 114 public boolean isAllowRenegotiate() |
115 { | 115 { |
116 return _allowRenegotiate; | 116 return _allowRenegotiate; |
117 } | 117 } |
118 | 118 |
119 /* ------------------------------------------------------------ */ | 119 /* ------------------------------------------------------------ */ |
120 /** | 120 /** |
121 * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered | 121 * Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered |
122 * a vulnerability in SSL/TLS with re-negotiation. If your JVM | 122 * a vulnerability in SSL/TLS with re-negotiation. If your JVM |
123 * does not have CVE-2009-3555 fixed, then re-negotiation should | 123 * does not have CVE-2009-3555 fixed, then re-negotiation should |
124 * not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban | 124 * not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban |
125 * of renegotiates in u19 and with RFC5746 in u22. | 125 * of renegotiates in u19 and with RFC5746 in u22. |
126 * | 126 * |
127 * @param allowRenegotiate | 127 * @param allowRenegotiate |
128 * true if re-negotiation is allowed (default false) | 128 * true if re-negotiation is allowed (default false) |
129 */ | 129 */ |
130 public void setAllowRenegotiate(boolean allowRenegotiate) | 130 public void setAllowRenegotiate(boolean allowRenegotiate) |
131 { | 131 { |
132 _allowRenegotiate = allowRenegotiate; | 132 _allowRenegotiate = allowRenegotiate; |
133 } | 133 } |
134 | 134 |
135 /* ------------------------------------------------------------ */ | 135 /* ------------------------------------------------------------ */ |
136 private void allocateBuffers() | 136 private void allocateBuffers() |
137 { | 137 { |
138 synchronized (this) | 138 synchronized (this) |
139 { | 139 { |
140 if (_allocations++==0) | 140 if (_allocations++==0) |
141 { | 141 { |
142 if (_buffers==null) | 142 if (_buffers==null) |
143 { | 143 { |
144 _buffers=__buffers.get(); | 144 _buffers=__buffers.get(); |
145 if (_buffers==null) | 145 if (_buffers==null) |
146 _buffers=new SslBuffers(_session.getPacketBufferSize()*2,_session.getApplicationBufferSize()*2); | 146 _buffers=new SslBuffers(_session.getPacketBufferSize()*2,_session.getApplicationBufferSize()*2); |
147 _inbound=_buffers._in; | 147 _inbound=_buffers._in; |
148 _outbound=_buffers._out; | 148 _outbound=_buffers._out; |
149 _unwrapBuf=_buffers._unwrap; | 149 _unwrapBuf=_buffers._unwrap; |
150 __buffers.set(null); | 150 __buffers.set(null); |
151 } | 151 } |
152 } | 152 } |
153 } | 153 } |
154 } | 154 } |
155 | 155 |
156 /* ------------------------------------------------------------ */ | 156 /* ------------------------------------------------------------ */ |
157 private void releaseBuffers() | 157 private void releaseBuffers() |
158 { | 158 { |
159 synchronized (this) | 159 synchronized (this) |
160 { | 160 { |
161 if (--_allocations==0) | 161 if (--_allocations==0) |
162 { | 162 { |
163 if (_buffers!=null && | 163 if (_buffers!=null && |
164 _inbound.length()==0 && | 164 _inbound.length()==0 && |
165 _outbound.length()==0 && | 165 _outbound.length()==0 && |
166 _unwrapBuf.length()==0) | 166 _unwrapBuf.length()==0) |
167 { | 167 { |
168 _inbound=null; | 168 _inbound=null; |
169 _outbound=null; | 169 _outbound=null; |
170 _unwrapBuf=null; | 170 _unwrapBuf=null; |
171 __buffers.set(_buffers); | 171 __buffers.set(_buffers); |
172 _buffers=null; | 172 _buffers=null; |
173 } | 173 } |
174 } | 174 } |
175 } | 175 } |
176 } | 176 } |
177 | 177 |
178 /* ------------------------------------------------------------ */ | 178 /* ------------------------------------------------------------ */ |
179 public Connection handle() throws IOException | 179 public Connection handle() throws IOException |
180 { | 180 { |
181 try | 181 try |
182 { | 182 { |
183 allocateBuffers(); | 183 allocateBuffers(); |
184 | 184 |
185 boolean progress=true; | 185 boolean progress=true; |
186 | 186 |
187 while (progress) | 187 while (progress) |
188 { | 188 { |
189 progress=false; | 189 progress=false; |
190 | 190 |
191 // If we are handshook let the delegate connection | 191 // If we are handshook let the delegate connection |
192 if (_engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING) | 192 if (_engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING) |
193 progress=process(null,null); | 193 progress=process(null,null); |
194 | 194 |
195 // handle the delegate connection | 195 // handle the delegate connection |
196 AsyncConnection next = (AsyncConnection)_connection.handle(); | 196 AsyncConnection next = (AsyncConnection)_connection.handle(); |
197 if (next!=_connection && next!=null) | 197 if (next!=_connection && next!=null) |
198 { | 198 { |
199 _connection=next; | 199 _connection=next; |
200 progress=true; | 200 progress=true; |
201 } | 201 } |
202 | 202 |
203 _logger.debug("{} handle {} progress={}", _session, this, progress); | 203 _logger.debug("{} handle {} progress={}", _session, this, progress); |
204 } | 204 } |
205 } | 205 } |
206 finally | 206 finally |
207 { | 207 { |
208 releaseBuffers(); | 208 releaseBuffers(); |
209 | 209 |
210 if (!_ishut && _sslEndPoint.isInputShutdown() && _sslEndPoint.isOpen()) | 210 if (!_ishut && _sslEndPoint.isInputShutdown() && _sslEndPoint.isOpen()) |
211 { | 211 { |
212 _ishut=true; | 212 _ishut=true; |
213 try | 213 try |
214 { | 214 { |
215 _connection.onInputShutdown(); | 215 _connection.onInputShutdown(); |
216 } | 216 } |
217 catch(Throwable x) | 217 catch(Throwable x) |
218 { | 218 { |
219 _logger.warn("onInputShutdown failed", x); | 219 _logger.warn("onInputShutdown failed", x); |
220 try{_sslEndPoint.close();} | 220 try{_sslEndPoint.close();} |
221 catch(IOException e2){ | 221 catch(IOException e2){ |
222 _logger.trace("",e2);} | 222 _logger.trace("",e2);} |
223 } | 223 } |
224 } | 224 } |
225 } | 225 } |
226 | 226 |
227 return this; | 227 return this; |
228 } | 228 } |
229 | 229 |
230 /* ------------------------------------------------------------ */ | 230 /* ------------------------------------------------------------ */ |
231 public boolean isIdle() | 231 public boolean isIdle() |
232 { | 232 { |
233 return false; | 233 return false; |
234 } | 234 } |
235 | 235 |
236 /* ------------------------------------------------------------ */ | 236 /* ------------------------------------------------------------ */ |
237 public boolean isSuspended() | 237 public boolean isSuspended() |
238 { | 238 { |
239 return false; | 239 return false; |
240 } | 240 } |
241 | 241 |
242 /* ------------------------------------------------------------ */ | 242 /* ------------------------------------------------------------ */ |
243 public void onClose() | 243 public void onClose() |
244 { | 244 { |
245 Connection connection = _sslEndPoint.getConnection(); | 245 Connection connection = _sslEndPoint.getConnection(); |
246 if (connection != null && connection != this) | 246 if (connection != null && connection != this) |
247 connection.onClose(); | 247 connection.onClose(); |
248 } | 248 } |
249 | 249 |
250 /* ------------------------------------------------------------ */ | 250 /* ------------------------------------------------------------ */ |
251 @Override | 251 @Override |
252 public void onIdleExpired(long idleForMs) | 252 public void onIdleExpired(long idleForMs) |
253 { | 253 { |
254 try | 254 try |
255 { | 255 { |
256 _logger.debug("onIdleExpired {}ms on {}",idleForMs,this); | 256 _logger.debug("onIdleExpired {}ms on {}",idleForMs,this); |
257 if (_endp.isOutputShutdown()) | 257 if (_endp.isOutputShutdown()) |
258 _sslEndPoint.close(); | 258 _sslEndPoint.close(); |
259 else | 259 else |
260 _sslEndPoint.shutdownOutput(); | 260 _sslEndPoint.shutdownOutput(); |
261 } | 261 } |
262 catch (IOException e) | 262 catch (IOException e) |
263 { | 263 { |
264 _logger.warn("",e); | 264 _logger.warn("",e); |
265 super.onIdleExpired(idleForMs); | 265 super.onIdleExpired(idleForMs); |
266 } | 266 } |
267 } | 267 } |
268 | 268 |
269 /* ------------------------------------------------------------ */ | 269 /* ------------------------------------------------------------ */ |
270 public void onInputShutdown() throws IOException | 270 public void onInputShutdown() throws IOException |
271 { | 271 { |
272 | 272 |
273 } | 273 } |
274 | 274 |
275 /* ------------------------------------------------------------ */ | 275 /* ------------------------------------------------------------ */ |
276 private synchronized boolean process(Buffer toFill, Buffer toFlush) throws IOException | 276 private synchronized boolean process(Buffer toFill, Buffer toFlush) throws IOException |
277 { | 277 { |
278 boolean some_progress=false; | 278 boolean some_progress=false; |
279 try | 279 try |
280 { | 280 { |
281 // We need buffers to progress | 281 // We need buffers to progress |
282 allocateBuffers(); | 282 allocateBuffers(); |
283 | 283 |
284 // if we don't have a buffer to put received data into | 284 // if we don't have a buffer to put received data into |
285 if (toFill==null) | 285 if (toFill==null) |
286 { | 286 { |
287 // use the unwrapbuffer to hold received data. | 287 // use the unwrapbuffer to hold received data. |
288 _unwrapBuf.compact(); | 288 _unwrapBuf.compact(); |
289 toFill=_unwrapBuf; | 289 toFill=_unwrapBuf; |
290 } | 290 } |
291 // Else if the fill buffer is too small for the SSL session | 291 // Else if the fill buffer is too small for the SSL session |
292 else if (toFill.capacity()<_session.getApplicationBufferSize()) | 292 else if (toFill.capacity()<_session.getApplicationBufferSize()) |
293 { | 293 { |
294 // fill to the temporary unwrapBuffer | 294 // fill to the temporary unwrapBuffer |
295 boolean progress=process(null,toFlush); | 295 boolean progress=process(null,toFlush); |
296 | 296 |
297 // if we received any data, | 297 // if we received any data, |
298 if (_unwrapBuf!=null && _unwrapBuf.hasContent()) | 298 if (_unwrapBuf!=null && _unwrapBuf.hasContent()) |
299 { | 299 { |
300 // transfer from temp buffer to fill buffer | 300 // transfer from temp buffer to fill buffer |
301 _unwrapBuf.skip(toFill.put(_unwrapBuf)); | 301 _unwrapBuf.skip(toFill.put(_unwrapBuf)); |
302 return true; | 302 return true; |
303 } | 303 } |
304 else | 304 else |
305 // return progress from recursive call | 305 // return progress from recursive call |
306 return progress; | 306 return progress; |
307 } | 307 } |
308 // Else if there is some temporary data | 308 // Else if there is some temporary data |
309 else if (_unwrapBuf!=null && _unwrapBuf.hasContent()) | 309 else if (_unwrapBuf!=null && _unwrapBuf.hasContent()) |
310 { | 310 { |
311 // transfer from temp buffer to fill buffer | 311 // transfer from temp buffer to fill buffer |
312 _unwrapBuf.skip(toFill.put(_unwrapBuf)); | 312 _unwrapBuf.skip(toFill.put(_unwrapBuf)); |
313 return true; | 313 return true; |
314 } | 314 } |
315 | 315 |
316 // If we are here, we have a buffer ready into which we can put some read data. | 316 // If we are here, we have a buffer ready into which we can put some read data. |
317 | 317 |
318 // If we have no data to flush, flush the empty buffer | 318 // If we have no data to flush, flush the empty buffer |
319 if (toFlush==null) | 319 if (toFlush==null) |
320 toFlush=__ZERO_BUFFER; | 320 toFlush=__ZERO_BUFFER; |
321 | 321 |
322 // While we are making progress processing SSL engine | 322 // While we are making progress processing SSL engine |
323 boolean progress=true; | 323 boolean progress=true; |
324 while (progress) | 324 while (progress) |
325 { | 325 { |
326 progress=false; | 326 progress=false; |
327 | 327 |
328 // Do any real IO | 328 // Do any real IO |
329 int filled=0,flushed=0; | 329 int filled=0,flushed=0; |
330 try | 330 try |
331 { | 331 { |
332 // Read any available data | 332 // Read any available data |
333 if (_inbound.space()>0 && (filled=_endp.fill(_inbound))>0) | 333 if (_inbound.space()>0 && (filled=_endp.fill(_inbound))>0) |
334 progress = true; | 334 progress = true; |
335 | 335 |
336 // flush any output data | 336 // flush any output data |
337 if (_outbound.hasContent() && (flushed=_endp.flush(_outbound))>0) | 337 if (_outbound.hasContent() && (flushed=_endp.flush(_outbound))>0) |
338 progress = true; | 338 progress = true; |
339 } | 339 } |
340 catch (IOException e) | 340 catch (IOException e) |
341 { | 341 { |
342 _endp.close(); | 342 _endp.close(); |
343 throw e; | 343 throw e; |
344 } | 344 } |
345 finally | 345 finally |
346 { | 346 { |
347 _logger.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length()); | 347 _logger.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length()); |
348 } | 348 } |
349 | 349 |
350 // handle the current hand share status | 350 // handle the current hand share status |
351 switch(_engine.getHandshakeStatus()) | 351 switch(_engine.getHandshakeStatus()) |
352 { | 352 { |
353 case FINISHED: | 353 case FINISHED: |
354 throw new IllegalStateException(); | 354 throw new IllegalStateException(); |
355 | 355 |
356 case NOT_HANDSHAKING: | 356 case NOT_HANDSHAKING: |
357 { | 357 { |
358 // Try unwrapping some application data | 358 // Try unwrapping some application data |
359 if (toFill.space()>0 && _inbound.hasContent() && unwrap(toFill)) | 359 if (toFill.space()>0 && _inbound.hasContent() && unwrap(toFill)) |
360 progress=true; | 360 progress=true; |
361 | 361 |
362 // Try wrapping some application data | 362 // Try wrapping some application data |
363 if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush)) | 363 if (toFlush.hasContent() && _outbound.space()>0 && wrap(toFlush)) |
364 progress=true; | 364 progress=true; |
365 } | 365 } |
366 break; | 366 break; |
367 | 367 |
368 case NEED_TASK: | 368 case NEED_TASK: |
369 { | 369 { |
370 // A task needs to be run, so run it! | 370 // A task needs to be run, so run it! |
371 Runnable task; | 371 Runnable task; |
372 while ((task=_engine.getDelegatedTask())!=null) | 372 while ((task=_engine.getDelegatedTask())!=null) |
373 { | 373 { |
374 progress=true; | 374 progress=true; |
375 task.run(); | 375 task.run(); |
376 } | 376 } |
377 | 377 |
378 } | 378 } |
379 break; | 379 break; |
380 | 380 |
381 case NEED_WRAP: | 381 case NEED_WRAP: |
382 { | 382 { |
383 // The SSL needs to send some handshake data to the other side | 383 // The SSL needs to send some handshake data to the other side |
384 if (_handshook && !_allowRenegotiate) | 384 if (_handshook && !_allowRenegotiate) |
385 _endp.close(); | 385 _endp.close(); |
386 else if (wrap(toFlush)) | 386 else if (wrap(toFlush)) |
387 progress=true; | 387 progress=true; |
388 } | 388 } |
389 break; | 389 break; |
390 | 390 |
391 case NEED_UNWRAP: | 391 case NEED_UNWRAP: |
392 { | 392 { |
393 // The SSL needs to receive some handshake data from the other side | 393 // The SSL needs to receive some handshake data from the other side |
394 if (_handshook && !_allowRenegotiate) | 394 if (_handshook && !_allowRenegotiate) |
395 _endp.close(); | 395 _endp.close(); |
396 else if (!_inbound.hasContent()&&filled==-1) | 396 else if (!_inbound.hasContent()&&filled==-1) |
397 { | 397 { |
398 // No more input coming | 398 // No more input coming |
399 _endp.shutdownInput(); | 399 _endp.shutdownInput(); |
400 } | 400 } |
401 else if (unwrap(toFill)) | 401 else if (unwrap(toFill)) |
402 progress=true; | 402 progress=true; |
403 } | 403 } |
404 break; | 404 break; |
405 } | 405 } |
406 | 406 |
407 // pass on ishut/oshut state | 407 // pass on ishut/oshut state |
408 if (_endp.isOpen() && _endp.isInputShutdown() && !_inbound.hasContent()) | 408 if (_endp.isOpen() && _endp.isInputShutdown() && !_inbound.hasContent()) |
409 closeInbound(); | 409 closeInbound(); |
410 | 410 |
411 if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent()) | 411 if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent()) |
412 _endp.shutdownOutput(); | 412 _endp.shutdownOutput(); |
413 | 413 |
414 // remember if any progress has been made | 414 // remember if any progress has been made |
415 some_progress|=progress; | 415 some_progress|=progress; |
416 } | 416 } |
417 | 417 |
418 // If we are reading into the temp buffer and it has some content, then we should be dispatched. | 418 // If we are reading into the temp buffer and it has some content, then we should be dispatched. |
419 if (toFill==_unwrapBuf && _unwrapBuf.hasContent() && !_connection.isSuspended()) | 419 if (toFill==_unwrapBuf && _unwrapBuf.hasContent() && !_connection.isSuspended()) |
420 _aEndp.dispatch(); | 420 _aEndp.dispatch(); |
421 } | 421 } |
422 finally | 422 finally |
423 { | 423 { |
424 releaseBuffers(); | 424 releaseBuffers(); |
425 if (some_progress) | 425 if (some_progress) |
426 _progressed.set(true); | 426 _progressed.set(true); |
427 } | 427 } |
428 return some_progress; | 428 return some_progress; |
429 } | 429 } |
430 | 430 |
431 private void closeInbound() | 431 private void closeInbound() |
432 { | 432 { |
433 try | 433 try |
434 { | 434 { |
435 _engine.closeInbound(); | 435 _engine.closeInbound(); |
436 } | 436 } |
437 catch (SSLException x) | 437 catch (SSLException x) |
438 { | 438 { |
439 _logger.debug("",x); | 439 _logger.debug("",x); |
440 } | 440 } |
441 } | 441 } |
442 | 442 |
443 private synchronized boolean wrap(final Buffer buffer) throws IOException | 443 private synchronized boolean wrap(final Buffer buffer) throws IOException |
444 { | 444 { |
445 ByteBuffer bbuf=extractByteBuffer(buffer); | 445 ByteBuffer bbuf=extractByteBuffer(buffer); |
446 final SSLEngineResult result; | 446 final SSLEngineResult result; |
447 | 447 |
448 synchronized(bbuf) | 448 synchronized(bbuf) |
449 { | 449 { |
450 _outbound.compact(); | 450 _outbound.compact(); |
451 ByteBuffer out_buffer=_outbound.getByteBuffer(); | 451 ByteBuffer out_buffer=_outbound.getByteBuffer(); |
452 synchronized(out_buffer) | 452 synchronized(out_buffer) |
453 { | 453 { |
454 try | 454 try |
455 { | 455 { |
456 bbuf.position(buffer.getIndex()); | 456 bbuf.position(buffer.getIndex()); |
457 bbuf.limit(buffer.putIndex()); | 457 bbuf.limit(buffer.putIndex()); |
458 out_buffer.position(_outbound.putIndex()); | 458 out_buffer.position(_outbound.putIndex()); |
459 out_buffer.limit(out_buffer.capacity()); | 459 out_buffer.limit(out_buffer.capacity()); |
460 result=_engine.wrap(bbuf,out_buffer); | 460 result=_engine.wrap(bbuf,out_buffer); |
461 if (_logger.isDebugEnabled()) | 461 if (_logger.isDebugEnabled()) |
462 _logger.debug("{} wrap {} {} consumed={} produced={}", | 462 _logger.debug("{} wrap {} {} consumed={} produced={}", |
463 _session, | 463 _session, |
464 result.getStatus(), | 464 result.getStatus(), |
465 result.getHandshakeStatus(), | 465 result.getHandshakeStatus(), |
466 result.bytesConsumed(), | 466 result.bytesConsumed(), |
467 result.bytesProduced()); | 467 result.bytesProduced()); |
468 | 468 |
469 | 469 |
470 buffer.skip(result.bytesConsumed()); | 470 buffer.skip(result.bytesConsumed()); |
471 _outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced()); | 471 _outbound.setPutIndex(_outbound.putIndex()+result.bytesProduced()); |
472 } | 472 } |
473 catch(SSLException e) | 473 catch(SSLException e) |
474 { | 474 { |
475 _logger.debug(String.valueOf(_endp), e); | 475 _logger.debug(String.valueOf(_endp), e); |
476 _endp.close(); | 476 _endp.close(); |
477 throw e; | 477 throw e; |
478 } | 478 } |
479 finally | 479 finally |
480 { | 480 { |
481 out_buffer.position(0); | 481 out_buffer.position(0); |
482 out_buffer.limit(out_buffer.capacity()); | 482 out_buffer.limit(out_buffer.capacity()); |
483 bbuf.position(0); | 483 bbuf.position(0); |
484 bbuf.limit(bbuf.capacity()); | 484 bbuf.limit(bbuf.capacity()); |
485 } | 485 } |
486 } | 486 } |
487 } | 487 } |
488 | 488 |
489 switch(result.getStatus()) | 489 switch(result.getStatus()) |
490 { | 490 { |
491 case BUFFER_UNDERFLOW: | 491 case BUFFER_UNDERFLOW: |
492 throw new IllegalStateException(); | 492 throw new IllegalStateException(); |
493 | 493 |
494 case BUFFER_OVERFLOW: | 494 case BUFFER_OVERFLOW: |
495 break; | 495 break; |
496 | 496 |
497 case OK: | 497 case OK: |
498 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) | 498 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) |
499 _handshook=true; | 499 _handshook=true; |
500 break; | 500 break; |
501 | 501 |
502 case CLOSED: | 502 case CLOSED: |
503 _logger.debug("wrap CLOSE {} {}",this,result); | 503 _logger.debug("wrap CLOSE {} {}",this,result); |
504 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) | 504 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) |
505 _endp.close(); | 505 _endp.close(); |
506 break; | 506 break; |
507 | 507 |
508 default: | 508 default: |
509 _logger.debug("{} wrap default {}",_session,result); | 509 _logger.debug("{} wrap default {}",_session,result); |
510 throw new IOException(result.toString()); | 510 throw new IOException(result.toString()); |
511 } | 511 } |
512 | 512 |
513 return result.bytesConsumed()>0 || result.bytesProduced()>0; | 513 return result.bytesConsumed()>0 || result.bytesProduced()>0; |
514 } | 514 } |
515 | 515 |
516 private synchronized boolean unwrap(final Buffer buffer) throws IOException | 516 private synchronized boolean unwrap(final Buffer buffer) throws IOException |
517 { | 517 { |
518 if (!_inbound.hasContent()) | 518 if (!_inbound.hasContent()) |
519 return false; | 519 return false; |
520 | 520 |
521 ByteBuffer bbuf=extractByteBuffer(buffer); | 521 ByteBuffer bbuf=extractByteBuffer(buffer); |
522 final SSLEngineResult result; | 522 final SSLEngineResult result; |
523 | 523 |
524 synchronized(bbuf) | 524 synchronized(bbuf) |
525 { | 525 { |
526 ByteBuffer in_buffer=_inbound.getByteBuffer(); | 526 ByteBuffer in_buffer=_inbound.getByteBuffer(); |
527 synchronized(in_buffer) | 527 synchronized(in_buffer) |
528 { | 528 { |
529 try | 529 try |
530 { | 530 { |
531 bbuf.position(buffer.putIndex()); | 531 bbuf.position(buffer.putIndex()); |
532 bbuf.limit(buffer.capacity()); | 532 bbuf.limit(buffer.capacity()); |
533 in_buffer.position(_inbound.getIndex()); | 533 in_buffer.position(_inbound.getIndex()); |
534 in_buffer.limit(_inbound.putIndex()); | 534 in_buffer.limit(_inbound.putIndex()); |
535 | 535 |
536 result=_engine.unwrap(in_buffer,bbuf); | 536 result=_engine.unwrap(in_buffer,bbuf); |
537 if (_logger.isDebugEnabled()) | 537 if (_logger.isDebugEnabled()) |
538 _logger.debug("{} unwrap {} {} consumed={} produced={}", | 538 _logger.debug("{} unwrap {} {} consumed={} produced={}", |
539 _session, | 539 _session, |
540 result.getStatus(), | 540 result.getStatus(), |
541 result.getHandshakeStatus(), | 541 result.getHandshakeStatus(), |
542 result.bytesConsumed(), | 542 result.bytesConsumed(), |
543 result.bytesProduced()); | 543 result.bytesProduced()); |
544 | 544 |
545 _inbound.skip(result.bytesConsumed()); | 545 _inbound.skip(result.bytesConsumed()); |
546 _inbound.compact(); | 546 _inbound.compact(); |
547 buffer.setPutIndex(buffer.putIndex()+result.bytesProduced()); | 547 buffer.setPutIndex(buffer.putIndex()+result.bytesProduced()); |
548 } | 548 } |
549 catch(SSLException e) | 549 catch(SSLException e) |
550 { | 550 { |
551 _logger.debug(String.valueOf(_endp), e); | 551 _logger.debug(String.valueOf(_endp), e); |
552 _endp.close(); | 552 _endp.close(); |
553 throw e; | 553 throw e; |
554 } | 554 } |
555 finally | 555 finally |
556 { | 556 { |
557 in_buffer.position(0); | 557 in_buffer.position(0); |
558 in_buffer.limit(in_buffer.capacity()); | 558 in_buffer.limit(in_buffer.capacity()); |
559 bbuf.position(0); | 559 bbuf.position(0); |
560 bbuf.limit(bbuf.capacity()); | 560 bbuf.limit(bbuf.capacity()); |
561 } | 561 } |
562 } | 562 } |
563 } | 563 } |
564 | 564 |
565 switch(result.getStatus()) | 565 switch(result.getStatus()) |
566 { | 566 { |
567 case BUFFER_UNDERFLOW: | 567 case BUFFER_UNDERFLOW: |
568 if (_endp.isInputShutdown()) | 568 if (_endp.isInputShutdown()) |
569 _inbound.clear(); | 569 _inbound.clear(); |
570 break; | 570 break; |
571 | 571 |
572 case BUFFER_OVERFLOW: | 572 case BUFFER_OVERFLOW: |
573 if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString()); | 573 if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString()); |
574 break; | 574 break; |
575 | 575 |
576 case OK: | 576 case OK: |
577 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) | 577 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) |
578 _handshook=true; | 578 _handshook=true; |
579 break; | 579 break; |
580 | 580 |
581 case CLOSED: | 581 case CLOSED: |
582 _logger.debug("unwrap CLOSE {} {}",this,result); | 582 _logger.debug("unwrap CLOSE {} {}",this,result); |
583 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) | 583 if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) |
584 _endp.close(); | 584 _endp.close(); |
585 break; | 585 break; |
586 | 586 |
587 default: | 587 default: |
588 _logger.debug("{} wrap default {}",_session,result); | 588 _logger.debug("{} wrap default {}",_session,result); |
589 throw new IOException(result.toString()); | 589 throw new IOException(result.toString()); |
590 } | 590 } |
591 | 591 |
592 //if (LOG.isDebugEnabled() && result.bytesProduced()>0) | 592 //if (LOG.isDebugEnabled() && result.bytesProduced()>0) |
593 // LOG.debug("{} unwrapped '{}'",_session,buffer); | 593 // LOG.debug("{} unwrapped '{}'",_session,buffer); |
594 | 594 |
595 return result.bytesConsumed()>0 || result.bytesProduced()>0; | 595 return result.bytesConsumed()>0 || result.bytesProduced()>0; |
596 } | 596 } |
597 | 597 |
598 | 598 |
599 /* ------------------------------------------------------------ */ | 599 /* ------------------------------------------------------------ */ |
600 private ByteBuffer extractByteBuffer(Buffer buffer) | 600 private ByteBuffer extractByteBuffer(Buffer buffer) |
601 { | 601 { |
602 if (buffer.buffer() instanceof NIOBuffer) | 602 if (buffer.buffer() instanceof NIOBuffer) |
603 return ((NIOBuffer)buffer.buffer()).getByteBuffer(); | 603 return ((NIOBuffer)buffer.buffer()).getByteBuffer(); |
604 return ByteBuffer.wrap(buffer.array()); | 604 return ByteBuffer.wrap(buffer.array()); |
605 } | 605 } |
606 | 606 |
607 /* ------------------------------------------------------------ */ | 607 /* ------------------------------------------------------------ */ |
608 public AsyncEndPoint getSslEndPoint() | 608 public AsyncEndPoint getSslEndPoint() |
609 { | 609 { |
610 return _sslEndPoint; | 610 return _sslEndPoint; |
611 } | 611 } |
612 | 612 |
613 /* ------------------------------------------------------------ */ | 613 /* ------------------------------------------------------------ */ |
614 public String toString() | 614 public String toString() |
615 { | 615 { |
616 return String.format("%s %s", super.toString(), _sslEndPoint); | 616 return String.format("%s %s", super.toString(), _sslEndPoint); |
617 } | 617 } |
618 | 618 |
619 /* ------------------------------------------------------------ */ | 619 /* ------------------------------------------------------------ */ |
620 /* ------------------------------------------------------------ */ | 620 /* ------------------------------------------------------------ */ |
621 public class SslEndPoint implements AsyncEndPoint | 621 public class SslEndPoint implements AsyncEndPoint |
622 { | 622 { |
623 public SSLEngine getSslEngine() | 623 public SSLEngine getSslEngine() |
624 { | 624 { |
625 return _engine; | 625 return _engine; |
626 } | 626 } |
627 | 627 |
628 public AsyncEndPoint getEndpoint() | 628 public AsyncEndPoint getEndpoint() |
629 { | 629 { |
630 return _aEndp; | 630 return _aEndp; |
631 } | 631 } |
632 | 632 |
633 public void shutdownOutput() throws IOException | 633 public void shutdownOutput() throws IOException |
634 { | 634 { |
635 synchronized (SslConnection.this) | 635 synchronized (SslConnection.this) |
636 { | 636 { |
637 _logger.debug("{} ssl endp.oshut {}",_session,this); | 637 _logger.debug("{} ssl endp.oshut {}",_session,this); |
638 _engine.closeOutbound(); | 638 _engine.closeOutbound(); |
639 _oshut=true; | 639 _oshut=true; |
640 } | 640 } |
641 flush(); | 641 flush(); |
642 } | 642 } |
643 | 643 |
644 public boolean isOutputShutdown() | 644 public boolean isOutputShutdown() |
645 { | 645 { |
646 synchronized (SslConnection.this) | 646 synchronized (SslConnection.this) |
647 { | 647 { |
648 return _oshut||!isOpen()||_engine.isOutboundDone(); | 648 return _oshut||!isOpen()||_engine.isOutboundDone(); |
649 } | 649 } |
650 } | 650 } |
651 | 651 |
652 public void shutdownInput() throws IOException | 652 public void shutdownInput() throws IOException |
653 { | 653 { |
654 _logger.debug("{} ssl endp.ishut!",_session); | 654 _logger.debug("{} ssl endp.ishut!",_session); |
655 // We do not do a closeInput here, as SSL does not support half close. | 655 // We do not do a closeInput here, as SSL does not support half close. |
656 // isInputShutdown works it out itself from buffer state and underlying endpoint state. | 656 // isInputShutdown works it out itself from buffer state and underlying endpoint state. |
657 } | 657 } |
658 | 658 |
659 public boolean isInputShutdown() | 659 public boolean isInputShutdown() |
660 { | 660 { |
661 synchronized (SslConnection.this) | 661 synchronized (SslConnection.this) |
662 { | 662 { |
663 return _endp.isInputShutdown() && | 663 return _endp.isInputShutdown() && |
664 !(_unwrapBuf!=null&&_unwrapBuf.hasContent()) && | 664 !(_unwrapBuf!=null&&_unwrapBuf.hasContent()) && |
665 !(_inbound!=null&&_inbound.hasContent()); | 665 !(_inbound!=null&&_inbound.hasContent()); |
666 } | 666 } |
667 } | 667 } |
668 | 668 |
669 public void close() throws IOException | 669 public void close() throws IOException |
670 { | 670 { |
671 _logger.debug("{} ssl endp.close",_session); | 671 _logger.debug("{} ssl endp.close",_session); |
672 _endp.close(); | 672 _endp.close(); |
673 } | 673 } |
674 | 674 |
675 public int fill(Buffer buffer) throws IOException | 675 public int fill(Buffer buffer) throws IOException |
676 { | 676 { |
677 int size=buffer.length(); | 677 int size=buffer.length(); |
678 process(buffer, null); | 678 process(buffer, null); |
679 | 679 |
680 int filled=buffer.length()-size; | 680 int filled=buffer.length()-size; |
681 | 681 |
682 if (filled==0 && isInputShutdown()) | 682 if (filled==0 && isInputShutdown()) |
683 return -1; | 683 return -1; |
684 return filled; | 684 return filled; |
685 } | 685 } |
686 | 686 |
687 public int flush(Buffer buffer) throws IOException | 687 public int flush(Buffer buffer) throws IOException |
688 { | 688 { |
689 int size = buffer.length(); | 689 int size = buffer.length(); |
690 process(null, buffer); | 690 process(null, buffer); |
691 return size-buffer.length(); | 691 return size-buffer.length(); |
692 } | 692 } |
693 | 693 |
694 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException | 694 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException |
695 { | 695 { |
696 if (header!=null && header.hasContent()) | 696 if (header!=null && header.hasContent()) |
697 return flush(header); | 697 return flush(header); |
698 if (buffer!=null && buffer.hasContent()) | 698 if (buffer!=null && buffer.hasContent()) |
699 return flush(buffer); | 699 return flush(buffer); |
700 if (trailer!=null && trailer.hasContent()) | 700 if (trailer!=null && trailer.hasContent()) |
701 return flush(trailer); | 701 return flush(trailer); |
702 return 0; | 702 return 0; |
703 } | 703 } |
704 | 704 |
705 public boolean blockReadable(long millisecs) throws IOException | 705 public boolean blockReadable(long millisecs) throws IOException |
706 { | 706 { |
707 long now = System.currentTimeMillis(); | 707 long now = System.currentTimeMillis(); |
708 long end=millisecs>0?(now+millisecs):Long.MAX_VALUE; | 708 long end=millisecs>0?(now+millisecs):Long.MAX_VALUE; |
709 | 709 |
710 while (now<end) | 710 while (now<end) |
711 { | 711 { |
712 if (process(null,null)) | 712 if (process(null,null)) |
713 break; | 713 break; |
714 _endp.blockReadable(end-now); | 714 _endp.blockReadable(end-now); |
715 now = System.currentTimeMillis(); | 715 now = System.currentTimeMillis(); |
716 } | 716 } |
717 | 717 |
718 return now<end; | 718 return now<end; |
719 } | 719 } |
720 | 720 |
721 public boolean blockWritable(long millisecs) throws IOException | 721 public boolean blockWritable(long millisecs) throws IOException |
722 { | 722 { |
723 return _endp.blockWritable(millisecs); | 723 return _endp.blockWritable(millisecs); |
724 } | 724 } |
725 | 725 |
726 public boolean isOpen() | 726 public boolean isOpen() |
727 { | 727 { |
728 return _endp.isOpen(); | 728 return _endp.isOpen(); |
729 } | 729 } |
730 | 730 |
731 public Object getTransport() | 731 public Object getTransport() |
732 { | 732 { |
733 return _endp; | 733 return _endp; |
734 } | 734 } |
735 | 735 |
736 public void flush() throws IOException | 736 public void flush() throws IOException |
737 { | 737 { |
738 process(null, null); | 738 process(null, null); |
739 } | 739 } |
740 | 740 |
741 public void dispatch() | 741 public void dispatch() |
742 { | 742 { |
743 _aEndp.dispatch(); | 743 _aEndp.dispatch(); |
744 } | 744 } |
745 | 745 |
746 public void asyncDispatch() | 746 public void asyncDispatch() |
747 { | 747 { |
748 _aEndp.asyncDispatch(); | 748 _aEndp.asyncDispatch(); |
749 } | 749 } |
750 | 750 |
751 public void scheduleWrite() | 751 public void scheduleWrite() |
752 { | 752 { |
753 _aEndp.scheduleWrite(); | 753 _aEndp.scheduleWrite(); |
754 } | 754 } |
755 | 755 |
756 public void onIdleExpired(long idleForMs) | 756 public void onIdleExpired(long idleForMs) |
757 { | 757 { |
758 _aEndp.onIdleExpired(idleForMs); | 758 _aEndp.onIdleExpired(idleForMs); |
759 } | 759 } |
760 | 760 |
761 public void setCheckForIdle(boolean check) | 761 public void setCheckForIdle(boolean check) |
762 { | 762 { |
763 _aEndp.setCheckForIdle(check); | 763 _aEndp.setCheckForIdle(check); |
764 } | 764 } |
765 | 765 |
766 public boolean isCheckForIdle() | 766 public boolean isCheckForIdle() |
767 { | 767 { |
768 return _aEndp.isCheckForIdle(); | 768 return _aEndp.isCheckForIdle(); |
769 } | 769 } |
770 | 770 |
771 public void scheduleTimeout(Task task, long timeoutMs) | 771 public boolean isWritable() |
772 { | 772 { |
773 _aEndp.scheduleTimeout(task,timeoutMs); | 773 return _aEndp.isWritable(); |
774 } | 774 } |
775 | 775 |
776 public void cancelTimeout(Task task) | 776 public boolean hasProgressed() |
777 { | 777 { |
778 _aEndp.cancelTimeout(task); | 778 return _progressed.getAndSet(false); |
779 } | 779 } |
780 | 780 |
781 public boolean isWritable() | 781 public String getLocalAddr() |
782 { | 782 { |
783 return _aEndp.isWritable(); | 783 return _aEndp.getLocalAddr(); |
784 } | 784 } |
785 | 785 |
786 public boolean hasProgressed() | 786 public String getLocalHost() |
787 { | 787 { |
788 return _progressed.getAndSet(false); | 788 return _aEndp.getLocalHost(); |
789 } | 789 } |
790 | 790 |
791 public String getLocalAddr() | 791 public int getLocalPort() |
792 { | 792 { |
793 return _aEndp.getLocalAddr(); | 793 return _aEndp.getLocalPort(); |
794 } | 794 } |
795 | 795 |
796 public String getLocalHost() | 796 public String getRemoteAddr() |
797 { | 797 { |
798 return _aEndp.getLocalHost(); | 798 return _aEndp.getRemoteAddr(); |
799 } | 799 } |
800 | 800 |
801 public int getLocalPort() | 801 public String getRemoteHost() |
802 { | 802 { |
803 return _aEndp.getLocalPort(); | 803 return _aEndp.getRemoteHost(); |
804 } | 804 } |
805 | 805 |
806 public String getRemoteAddr() | 806 public int getRemotePort() |
807 { | 807 { |
808 return _aEndp.getRemoteAddr(); | 808 return _aEndp.getRemotePort(); |
809 } | 809 } |
810 | 810 |
811 public String getRemoteHost() | 811 public boolean isBlocking() |
812 { | 812 { |
813 return _aEndp.getRemoteHost(); | 813 return false; |
814 } | 814 } |
815 | 815 |
816 public int getRemotePort() | 816 public int getMaxIdleTime() |
817 { | 817 { |
818 return _aEndp.getRemotePort(); | 818 return _aEndp.getMaxIdleTime(); |
819 } | 819 } |
820 | 820 |
821 public boolean isBlocking() | 821 public void setMaxIdleTime(int timeMs) throws IOException |
822 { | 822 { |
823 return false; | 823 _aEndp.setMaxIdleTime(timeMs); |
824 } | 824 } |
825 | 825 |
826 public int getMaxIdleTime() | 826 public Connection getConnection() |
827 { | 827 { |
828 return _aEndp.getMaxIdleTime(); | 828 return _connection; |
829 } | 829 } |
830 | 830 |
831 public void setMaxIdleTime(int timeMs) throws IOException | 831 public void setConnection(Connection connection) |
832 { | 832 { |
833 _aEndp.setMaxIdleTime(timeMs); | 833 _connection=(AsyncConnection)connection; |
834 } | 834 } |
835 | 835 |
836 public Connection getConnection() | 836 public String toString() |
837 { | 837 { |
838 return _connection; | 838 // Do NOT use synchronized (SslConnection.this) |
839 } | 839 // because it's very easy to deadlock when debugging is enabled. |
840 | 840 // We do a best effort to print the right toString() and that's it. |
841 public void setConnection(Connection connection) | 841 Buffer inbound = _inbound; |
842 { | 842 Buffer outbound = _outbound; |
843 _connection=(AsyncConnection)connection; | 843 Buffer unwrap = _unwrapBuf; |
844 } | 844 int i = inbound == null? -1 : inbound.length(); |
845 | 845 int o = outbound == null ? -1 : outbound.length(); |
846 public String toString() | 846 int u = unwrap == null ? -1 : unwrap.length(); |
847 { | 847 return String.format("SSL %s i/o/u=%d/%d/%d ishut=%b oshut=%b {%s}", |
848 // Do NOT use synchronized (SslConnection.this) | 848 _engine.getHandshakeStatus(), |
849 // because it's very easy to deadlock when debugging is enabled. | 849 i, o, u, |
850 // We do a best effort to print the right toString() and that's it. | 850 _ishut, _oshut, |
851 Buffer inbound = _inbound; | 851 _connection); |
852 Buffer outbound = _outbound; | 852 } |
853 Buffer unwrap = _unwrapBuf; | 853 |
854 int i = inbound == null? -1 : inbound.length(); | 854 } |
855 int o = outbound == null ? -1 : outbound.length(); | |
856 int u = unwrap == null ? -1 : unwrap.length(); | |
857 return String.format("SSL %s i/o/u=%d/%d/%d ishut=%b oshut=%b {%s}", | |
858 _engine.getHandshakeStatus(), | |
859 i, o, u, | |
860 _ishut, _oshut, | |
861 _connection); | |
862 } | |
863 | |
864 } | |
865 } | 855 } |