26 package jdk.incubator.http; |
26 package jdk.incubator.http; |
27 |
27 |
28 import java.io.IOException; |
28 import java.io.IOException; |
29 import java.nio.ByteBuffer; |
29 import java.nio.ByteBuffer; |
30 import java.nio.channels.SocketChannel; |
30 import java.nio.channels.SocketChannel; |
31 import java.util.Arrays; |
|
32 import java.util.List; |
|
33 import java.util.concurrent.locks.Lock; |
31 import java.util.concurrent.locks.Lock; |
34 import java.util.concurrent.locks.ReentrantLock; |
32 import java.util.concurrent.locks.ReentrantLock; |
35 import javax.net.ssl.SSLEngineResult.HandshakeStatus; |
33 import javax.net.ssl.SSLEngineResult.HandshakeStatus; |
36 import javax.net.ssl.SSLEngineResult.Status; |
34 import javax.net.ssl.SSLEngineResult.Status; |
37 import javax.net.ssl.*; |
35 import javax.net.ssl.*; |
39 import jdk.incubator.http.internal.common.Utils; |
37 import jdk.incubator.http.internal.common.Utils; |
40 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; |
38 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; |
41 |
39 |
42 /** |
40 /** |
43 * Implements the mechanics of SSL by managing an SSLEngine object. |
41 * Implements the mechanics of SSL by managing an SSLEngine object. |
44 * One of these is associated with each SSLConnection. |
42 * <p> |
|
43 * This class is only used to implement the {@link |
|
44 * AbstractAsyncSSLConnection.SSLConnectionChannel} which is handed of |
|
45 * to RawChannelImpl when creating a WebSocket. |
45 */ |
46 */ |
46 class SSLDelegate { |
47 class SSLDelegate { |
47 |
48 |
48 final SSLEngine engine; |
49 final SSLEngine engine; |
49 final EngineWrapper wrapper; |
50 final EngineWrapper wrapper; |
50 final Lock handshaking = new ReentrantLock(); |
51 final Lock handshaking = new ReentrantLock(); |
51 final SSLParameters sslParameters; |
|
52 final SocketChannel chan; |
52 final SocketChannel chan; |
53 final HttpClientImpl client; |
53 |
54 final String serverName; |
54 SSLDelegate(SSLEngine eng, SocketChannel chan) |
55 |
|
56 SSLDelegate(SSLEngine eng, SocketChannel chan, HttpClientImpl client, String sn) |
|
57 { |
55 { |
58 this.engine = eng; |
56 this.engine = eng; |
59 this.chan = chan; |
57 this.chan = chan; |
60 this.client = client; |
|
61 this.wrapper = new EngineWrapper(chan, engine); |
58 this.wrapper = new EngineWrapper(chan, engine); |
62 this.sslParameters = engine.getSSLParameters(); |
|
63 this.serverName = sn; |
|
64 } |
59 } |
65 |
60 |
66 // alpn[] may be null |
61 // alpn[] may be null |
67 SSLDelegate(SocketChannel chan, HttpClientImpl client, String[] alpn, String sn) |
62 // SSLDelegate(SocketChannel chan, HttpClientImpl client, String[] alpn, String sn) |
68 throws IOException |
63 // throws IOException |
69 { |
64 // { |
70 serverName = sn; |
65 // serverName = sn; |
71 SSLContext context = client.sslContext(); |
66 // SSLContext context = client.sslContext(); |
72 engine = context.createSSLEngine(); |
67 // engine = context.createSSLEngine(); |
73 engine.setUseClientMode(true); |
68 // engine.setUseClientMode(true); |
74 SSLParameters sslp = client.sslParameters() |
69 // SSLParameters sslp = client.sslParameters(); |
75 .orElseGet(context::getSupportedSSLParameters); |
70 // sslParameters = Utils.copySSLParameters(sslp); |
76 sslParameters = Utils.copySSLParameters(sslp); |
71 // if (sn != null) { |
77 if (sn != null) { |
72 // SNIHostName sni = new SNIHostName(sn); |
78 SNIHostName sni = new SNIHostName(sn); |
73 // sslParameters.setServerNames(List.of(sni)); |
79 sslParameters.setServerNames(List.of(sni)); |
74 // } |
80 } |
75 // if (alpn != null) { |
81 if (alpn != null) { |
76 // sslParameters.setApplicationProtocols(alpn); |
82 sslParameters.setApplicationProtocols(alpn); |
77 // Log.logSSL("SSLDelegate: Setting application protocols: {0}" + Arrays.toString(alpn)); |
83 Log.logSSL("SSLDelegate: Setting application protocols: {0}" + Arrays.toString(alpn)); |
78 // } else { |
84 } else { |
79 // Log.logSSL("SSLDelegate: No application protocols proposed"); |
85 Log.logSSL("SSLDelegate: No application protocols proposed"); |
80 // } |
86 } |
81 // engine.setSSLParameters(sslParameters); |
87 engine.setSSLParameters(sslParameters); |
82 // wrapper = new EngineWrapper(chan, engine); |
88 wrapper = new EngineWrapper(chan, engine); |
83 // this.chan = chan; |
89 this.chan = chan; |
84 // this.client = client; |
90 this.client = client; |
85 // } |
91 } |
86 |
92 |
87 // SSLParameters getSSLParameters() { |
93 SSLParameters getSSLParameters() { |
88 // return sslParameters; |
94 return sslParameters; |
89 // } |
95 } |
90 |
96 |
91 static long countBytes(ByteBuffer[] buffers, int start, int number) { |
97 private static long countBytes(ByteBuffer[] buffers, int start, int number) { |
|
98 long c = 0; |
92 long c = 0; |
99 for (int i=0; i<number; i++) { |
93 for (int i=0; i<number; i++) { |
100 c+= buffers[start+i].remaining(); |
94 c+= buffers[start+i].remaining(); |
101 } |
95 } |
102 return c; |
96 return c; |
318 u_remaining = unwrap_src.remaining(); |
313 u_remaining = unwrap_src.remaining(); |
319 return r; |
314 return r; |
320 } |
315 } |
321 } |
316 } |
322 |
317 |
323 WrapperResult sendData (ByteBuffer src) throws IOException { |
318 // WrapperResult sendData (ByteBuffer src) throws IOException { |
324 ByteBuffer[] buffers = new ByteBuffer[1]; |
319 // ByteBuffer[] buffers = new ByteBuffer[1]; |
325 buffers[0] = src; |
320 // buffers[0] = src; |
326 return sendData(buffers, 0, 1); |
321 // return sendData(buffers, 0, 1); |
327 } |
322 // } |
328 |
323 |
329 /** |
324 /** |
330 * send the data in the given ByteBuffer. If a handshake is needed |
325 * send the data in the given ByteBuffer. If a handshake is needed |
331 * then this is handled within this method. When this call returns, |
326 * then this is handled within this method. When this call returns, |
332 * all of the given user data has been sent and any handshake has been |
327 * all of the given user data has been sent and any handshake has been |
405 * on the wrapper methods being idempotent. eg. if wrapAndSend() |
400 * on the wrapper methods being idempotent. eg. if wrapAndSend() |
406 * is called with no data to send then there must be no problem |
401 * is called with no data to send then there must be no problem |
407 */ |
402 */ |
408 @SuppressWarnings("fallthrough") |
403 @SuppressWarnings("fallthrough") |
409 void doHandshake (HandshakeStatus hs_status) throws IOException { |
404 void doHandshake (HandshakeStatus hs_status) throws IOException { |
410 boolean wasBlocking = false; |
405 boolean wasBlocking; |
411 try { |
406 try { |
412 wasBlocking = chan.isBlocking(); |
407 wasBlocking = chan.isBlocking(); |
413 handshaking.lock(); |
408 handshaking.lock(); |
414 chan.configureBlocking(true); |
409 chan.configureBlocking(true); |
415 ByteBuffer tmp = allocate(BufType.APPLICATION); |
410 ByteBuffer tmp = allocate(BufType.APPLICATION); |
451 } finally { |
446 } finally { |
452 handshaking.unlock(); |
447 handshaking.unlock(); |
453 } |
448 } |
454 } |
449 } |
455 |
450 |
456 static void printParams(SSLParameters p) { |
451 // static void printParams(SSLParameters p) { |
457 System.out.println("SSLParameters:"); |
452 // System.out.println("SSLParameters:"); |
458 if (p == null) { |
453 // if (p == null) { |
459 System.out.println("Null params"); |
454 // System.out.println("Null params"); |
460 return; |
455 // return; |
461 } |
456 // } |
462 for (String cipher : p.getCipherSuites()) { |
457 // for (String cipher : p.getCipherSuites()) { |
463 System.out.printf("cipher: %s\n", cipher); |
458 // System.out.printf("cipher: %s\n", cipher); |
464 } |
459 // } |
465 // JDK 8 EXCL START |
460 // // JDK 8 EXCL START |
466 for (String approto : p.getApplicationProtocols()) { |
461 // for (String approto : p.getApplicationProtocols()) { |
467 System.out.printf("application protocol: %s\n", approto); |
462 // System.out.printf("application protocol: %s\n", approto); |
468 } |
463 // } |
469 // JDK 8 EXCL END |
464 // // JDK 8 EXCL END |
470 for (String protocol : p.getProtocols()) { |
465 // for (String protocol : p.getProtocols()) { |
471 System.out.printf("protocol: %s\n", protocol); |
466 // System.out.printf("protocol: %s\n", protocol); |
472 } |
467 // } |
473 if (p.getServerNames() != null) { |
468 // if (p.getServerNames() != null) { |
474 for (SNIServerName sname : p.getServerNames()) { |
469 // for (SNIServerName sname : p.getServerNames()) { |
475 System.out.printf("server name: %s\n", sname.toString()); |
470 // System.out.printf("server name: %s\n", sname.toString()); |
476 } |
471 // } |
477 } |
472 // } |
478 } |
473 // } |
479 |
474 |
480 String getSessionInfo() { |
475 String getSessionInfo() { |
481 StringBuilder sb = new StringBuilder(); |
476 StringBuilder sb = new StringBuilder(); |
482 String application = engine.getApplicationProtocol(); |
477 String application = engine.getApplicationProtocol(); |
483 SSLSession sess = engine.getSession(); |
478 SSLSession sess = engine.getSession(); |