< prev index next >
1 /*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 */
24 package java.net.http;
25
26 import java.io.IOException;
27 import java.io.UncheckedIOException;
28 import java.net.InetSocketAddress;
29 import java.nio.ByteBuffer;
30 import java.nio.channels.SocketChannel;
31 import java.security.AccessControlContext;
32 import java.util.concurrent.CompletableFuture;
33 import javax.net.ssl.SSLEngineResult.Status;
34 import javax.net.ssl.SSLParameters;
35 import java.net.http.SSLDelegate.BufType;
36 import java.net.http.SSLDelegate.WrapperResult;
37
38 /**
39 * An SSL tunnel built on a Plain (CONNECT) TCP tunnel.
40 */
41 class SSLTunnelConnection extends HttpConnection {
42
43 final PlainTunnelingConnection delegate;
44 protected SSLDelegate sslDelegate;
45 private volatile boolean connected;
46
47 @Override
48 public void connect() throws IOException, InterruptedException {
49 delegate.connect();
50 this.sslDelegate = new SSLDelegate(delegate.channel(), client, null);
51 connected = true;
52 }
53
54 @Override
55 boolean connected() {
56 return connected && delegate.connected();
57 }
58
59 @Override
60 public CompletableFuture<Void> connectAsync() {
61 return delegate.connectAsync()
62 .thenAccept((Void v) -> {
63 try {
64 // can this block?
65 this.sslDelegate = new SSLDelegate(delegate.channel(),
66 client,
67 null);
68 connected = true;
69 } catch (IOException e) {
70 throw new UncheckedIOException(e);
71 }
72 });
73 }
74
75 SSLTunnelConnection(InetSocketAddress addr,
76 HttpClientImpl client,
77 InetSocketAddress proxy,
78 AccessControlContext acc) {
79 super(addr, client);
80 delegate = new PlainTunnelingConnection(addr, proxy, client, acc);
81 }
82
83 @Override
84 SSLParameters sslParameters() {
85 return sslDelegate.getSSLParameters();
86 }
87
88 @Override
89 public String toString() {
90 return "SSLTunnelConnection: " + super.toString();
91 }
92
93 private static long countBytes(ByteBuffer[] buffers, int start, int number) {
94 long c = 0;
95 for (int i=0; i<number; i++) {
96 c+= buffers[start+i].remaining();
97 }
98 return c;
99 }
100
101 @Override
102 ConnectionPool.CacheKey cacheKey() {
103 return ConnectionPool.cacheKey(address, delegate.proxyAddr);
104 }
105
106 @Override
107 long write(ByteBuffer[] buffers, int start, int number) throws IOException {
108 //debugPrint("Send", buffers, start, number);
109 long l = countBytes(buffers, start, number);
110 WrapperResult r = sslDelegate.sendData(buffers, start, number);
111 if (r.result.getStatus() == Status.CLOSED) {
112 if (l > 0) {
113 throw new IOException("SSLHttpConnection closed");
114 }
115 }
116 return l;
117 }
118
119 @Override
120 long write(ByteBuffer buffer) throws IOException {
121 //debugPrint("Send", buffer);
122 long l = buffer.remaining();
123 WrapperResult r = sslDelegate.sendData(buffer);
124 if (r.result.getStatus() == Status.CLOSED) {
125 if (l > 0) {
126 throw new IOException("SSLHttpConnection closed");
127 }
128 }
129 return l;
130 }
131
132 @Override
133 void close() {
134 try {
135 //System.err.println ("Closing: " + this);
136 delegate.channel().close(); // TODO: proper close
137 } catch (IOException ex) {
138 }
139 }
140
141 @Override
142 protected ByteBuffer readImpl(int length) throws IOException {
143 ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length);
144 WrapperResult r = sslDelegate.recvData(buf);
145 // TODO: check for closure
146 String s = "Receive) ";
147 //debugPrint(s, r.buf);
148 return r.buf;
149 }
150
151 @Override
152 protected int readImpl(ByteBuffer buf) throws IOException {
153 WrapperResult r = sslDelegate.recvData(buf);
154 // TODO: check for closure
155 String s = "Receive) ";
156 //debugPrint(s, r.buf);
157 return r.result.bytesProduced();
158 }
159
160 @Override
161 SocketChannel channel() {
162 return delegate.channel();
163 }
164
165 @Override
166 CompletableFuture<Void> whenReceivingResponse() {
167 return delegate.whenReceivingResponse();
168 }
169
170 @Override
171 boolean isSecure() {
172 return true;
173 }
174
175 @Override
176 boolean isProxied() {
177 return true;
178 }
179 }
< prev index next >