1 /*
2 * Copyright (c) 2000, 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 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.*;
29 import java.net.*;
30 import java.nio.*;
31 import java.nio.channels.*;
32 import java.security.AccessController;
33 import java.security.PrivilegedExceptionAction;
34 import java.util.concurrent.TimeUnit;
35
36 // Make a socket channel look like a socket.
37 //
38 // The only aspects of java.net.Socket-hood that we don't attempt to emulate
39 // here are the interrupted-I/O exceptions (which our Solaris implementations
40 // attempt to support) and the sending of urgent data. Otherwise an adapted
41 // socket should look enough like a real java.net.Socket to fool most of the
42 // developers most of the time, right down to the exception message strings.
43 //
44 // The methods in this class are defined in exactly the same order as in
45 // java.net.Socket so as to simplify tracking future changes to that class.
46 //
47
48 public class SocketAdaptor
49 extends Socket
50 {
51
52 // The channel being adapted
53 private final SocketChannelImpl sc;
54
55 // Timeout "option" value for reads
56 private volatile int timeout;
57
58 private SocketAdaptor(SocketChannelImpl sc) throws SocketException {
59 super((SocketImpl) null);
60 this.sc = sc;
61 }
62
63 public static Socket create(SocketChannelImpl sc) {
64 try {
65 return new SocketAdaptor(sc);
66 } catch (SocketException e) {
67 throw new InternalError("Should not reach here");
68 }
72 return sc;
73 }
74
75 // Override this method just to protect against changes in the superclass
76 //
77 public void connect(SocketAddress remote) throws IOException {
78 connect(remote, 0);
79 }
80
81 public void connect(SocketAddress remote, int timeout) throws IOException {
82 if (remote == null)
83 throw new IllegalArgumentException("connect: The address can't be null");
84 if (timeout < 0)
85 throw new IllegalArgumentException("connect: timeout can't be negative");
86
87 synchronized (sc.blockingLock()) {
88 if (!sc.isBlocking())
89 throw new IllegalBlockingModeException();
90
91 try {
92
93 if (timeout == 0) {
94 sc.connect(remote);
95 return;
96 }
97
98 sc.configureBlocking(false);
99 try {
100 if (sc.connect(remote))
101 return;
102 long timeoutNanos =
103 TimeUnit.NANOSECONDS.convert(timeout,
104 TimeUnit.MILLISECONDS);
105 for (;;) {
106 if (!sc.isOpen())
107 throw new ClosedChannelException();
108 long startTime = System.nanoTime();
109
110 int result = sc.poll(Net.POLLCONN, timeout);
111 if (result > 0 && sc.finishConnect())
112 break;
113 timeoutNanos -= System.nanoTime() - startTime;
114 if (timeoutNanos <= 0) {
115 try {
116 sc.close();
117 } catch (IOException x) { }
118 throw new SocketTimeoutException();
119 }
120 }
121 } finally {
122 if (sc.isOpen())
123 sc.configureBlocking(true);
124 }
125
126 } catch (Exception x) {
127 Net.translateException(x, true);
128 }
129 }
130
131 }
132
133 public void bind(SocketAddress local) throws IOException {
134 try {
135 sc.bind(local);
136 } catch (Exception x) {
137 Net.translateException(x);
138 }
139 }
140
141 public InetAddress getInetAddress() {
142 SocketAddress remote = sc.remoteAddress();
143 if (remote == null) {
171 if (local == null) {
172 return -1;
173 } else {
174 return ((InetSocketAddress)local).getPort();
175 }
176 }
177
178 private class SocketInputStream
179 extends ChannelInputStream
180 {
181 private SocketInputStream() {
182 super(sc);
183 }
184
185 protected int read(ByteBuffer bb)
186 throws IOException
187 {
188 synchronized (sc.blockingLock()) {
189 if (!sc.isBlocking())
190 throw new IllegalBlockingModeException();
191 if (timeout == 0)
192 return sc.read(bb);
193 sc.configureBlocking(false);
194
195 try {
196 int n;
197 if ((n = sc.read(bb)) != 0)
198 return n;
199 long timeoutNanos =
200 TimeUnit.NANOSECONDS.convert(timeout,
201 TimeUnit.MILLISECONDS);
202 for (;;) {
203 if (!sc.isOpen())
204 throw new ClosedChannelException();
205 long startTime = System.nanoTime();
206 int result = sc.poll(Net.POLLIN, timeout);
207 if (result > 0) {
208 if ((n = sc.read(bb)) != 0)
209 return n;
210 }
211 timeoutNanos -= System.nanoTime() - startTime;
212 if (timeoutNanos <= 0)
213 throw new SocketTimeoutException();
214 }
215 } finally {
216 if (sc.isOpen())
217 sc.configureBlocking(true);
218 }
219
220 }
221 }
222 }
223
224 private InputStream socketInputStream = null;
225
226 public InputStream getInputStream() throws IOException {
227 if (!sc.isOpen())
228 throw new SocketException("Socket is closed");
229 if (!sc.isConnected())
230 throw new SocketException("Socket is not connected");
231 if (!sc.isInputOpen())
232 throw new SocketException("Socket input is shutdown");
233 if (socketInputStream == null) {
234 try {
235 socketInputStream = AccessController.doPrivileged(
236 new PrivilegedExceptionAction<InputStream>() {
237 public InputStream run() throws IOException {
238 return new SocketInputStream();
239 }
|
1 /*
2 * Copyright (c) 2000, 2018, 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 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.net.InetAddress;
32 import java.net.InetSocketAddress;
33 import java.net.Socket;
34 import java.net.SocketAddress;
35 import java.net.SocketException;
36 import java.net.SocketImpl;
37 import java.net.SocketOption;
38 import java.net.SocketTimeoutException;
39 import java.net.StandardSocketOptions;
40 import java.nio.ByteBuffer;
41 import java.nio.channels.Channels;
42 import java.nio.channels.ClosedChannelException;
43 import java.nio.channels.IllegalBlockingModeException;
44 import java.nio.channels.SocketChannel;
45 import java.security.AccessController;
46 import java.security.PrivilegedExceptionAction;
47 import java.util.concurrent.TimeUnit;
48
49 // Make a socket channel look like a socket.
50 //
51 // The only aspects of java.net.Socket-hood that we don't attempt to emulate
52 // here are the interrupted-I/O exceptions (which our Solaris implementations
53 // attempt to support) and the sending of urgent data. Otherwise an adapted
54 // socket should look enough like a real java.net.Socket to fool most of the
55 // developers most of the time, right down to the exception message strings.
56 //
57 // The methods in this class are defined in exactly the same order as in
58 // java.net.Socket so as to simplify tracking future changes to that class.
59 //
60
61 class SocketAdaptor
62 extends Socket
63 {
64
65 // The channel being adapted
66 private final SocketChannelImpl sc;
67
68 // Timeout "option" value for reads
69 private volatile int timeout;
70
71 private SocketAdaptor(SocketChannelImpl sc) throws SocketException {
72 super((SocketImpl) null);
73 this.sc = sc;
74 }
75
76 public static Socket create(SocketChannelImpl sc) {
77 try {
78 return new SocketAdaptor(sc);
79 } catch (SocketException e) {
80 throw new InternalError("Should not reach here");
81 }
85 return sc;
86 }
87
88 // Override this method just to protect against changes in the superclass
89 //
90 public void connect(SocketAddress remote) throws IOException {
91 connect(remote, 0);
92 }
93
94 public void connect(SocketAddress remote, int timeout) throws IOException {
95 if (remote == null)
96 throw new IllegalArgumentException("connect: The address can't be null");
97 if (timeout < 0)
98 throw new IllegalArgumentException("connect: timeout can't be negative");
99
100 synchronized (sc.blockingLock()) {
101 if (!sc.isBlocking())
102 throw new IllegalBlockingModeException();
103
104 try {
105 if (timeout == 0) {
106 sc.connect(remote);
107 return;
108 }
109
110 sc.configureBlocking(false);
111 try {
112 if (sc.connect(remote))
113 return;
114 long timeoutNanos =
115 TimeUnit.NANOSECONDS.convert(timeout,
116 TimeUnit.MILLISECONDS);
117 for (;;) {
118 if (!sc.isOpen())
119 throw new ClosedChannelException();
120 long startTime = System.nanoTime();
121
122 int result = sc.poll(Net.POLLCONN, timeout);
123 if (result > 0 && sc.finishConnect())
124 break;
125 timeoutNanos -= System.nanoTime() - startTime;
126 if (timeoutNanos <= 0) {
127 try {
128 sc.close();
129 } catch (IOException x) { }
130 throw new SocketTimeoutException();
131 }
132 }
133 } finally {
134 try {
135 sc.configureBlocking(true);
136 } catch (ClosedChannelException e) { }
137 }
138
139 } catch (Exception x) {
140 Net.translateException(x, true);
141 }
142 }
143
144 }
145
146 public void bind(SocketAddress local) throws IOException {
147 try {
148 sc.bind(local);
149 } catch (Exception x) {
150 Net.translateException(x);
151 }
152 }
153
154 public InetAddress getInetAddress() {
155 SocketAddress remote = sc.remoteAddress();
156 if (remote == null) {
184 if (local == null) {
185 return -1;
186 } else {
187 return ((InetSocketAddress)local).getPort();
188 }
189 }
190
191 private class SocketInputStream
192 extends ChannelInputStream
193 {
194 private SocketInputStream() {
195 super(sc);
196 }
197
198 protected int read(ByteBuffer bb)
199 throws IOException
200 {
201 synchronized (sc.blockingLock()) {
202 if (!sc.isBlocking())
203 throw new IllegalBlockingModeException();
204
205 if (timeout == 0)
206 return sc.read(bb);
207
208 sc.configureBlocking(false);
209 try {
210 int n;
211 if ((n = sc.read(bb)) != 0)
212 return n;
213 long timeoutNanos =
214 TimeUnit.NANOSECONDS.convert(timeout,
215 TimeUnit.MILLISECONDS);
216 for (;;) {
217 if (!sc.isOpen())
218 throw new ClosedChannelException();
219 long startTime = System.nanoTime();
220 int result = sc.poll(Net.POLLIN, timeout);
221 if (result > 0) {
222 if ((n = sc.read(bb)) != 0)
223 return n;
224 }
225 timeoutNanos -= System.nanoTime() - startTime;
226 if (timeoutNanos <= 0)
227 throw new SocketTimeoutException();
228 }
229 } finally {
230 try {
231 sc.configureBlocking(true);
232 } catch (ClosedChannelException e) { }
233 }
234 }
235 }
236 }
237
238 private InputStream socketInputStream = null;
239
240 public InputStream getInputStream() throws IOException {
241 if (!sc.isOpen())
242 throw new SocketException("Socket is closed");
243 if (!sc.isConnected())
244 throw new SocketException("Socket is not connected");
245 if (!sc.isInputOpen())
246 throw new SocketException("Socket input is shutdown");
247 if (socketInputStream == null) {
248 try {
249 socketInputStream = AccessController.doPrivileged(
250 new PrivilegedExceptionAction<InputStream>() {
251 public InputStream run() throws IOException {
252 return new SocketInputStream();
253 }
|