1/*
2 * Copyright (c) 2007, 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 */
25package java.net;
26
27import java.io.*;
28import java.security.AccessController;
29import java.security.PrivilegedAction;
30import sun.security.action.GetPropertyAction;
31
32/*
33 * This class PlainSocketImpl simply delegates to the appropriate real
34 * SocketImpl. We do this because PlainSocketImpl is already extended
35 * by SocksSocketImpl.
36 * <p>
37 * There are two possibilities for the real SocketImpl,
38 * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use
39 * DualStackPlainSocketImpl on systems that have a dual stack
40 * TCP implementation. Otherwise we create an instance of
41 * TwoStacksPlainSocketImpl and delegate to it.
42 *
43 * @author Chris Hegarty
44 */
45
46class PlainSocketImpl extends AbstractPlainSocketImpl
47{
48    private AbstractPlainSocketImpl impl;
49
50    /* java.net.preferIPv4Stack */
51    private static final boolean preferIPv4Stack;
52
53    /* True if exclusive binding is on for Windows */
54    private static final boolean exclusiveBind;
55
56    static {
57        preferIPv4Stack = Boolean.parseBoolean(
58        AccessController.doPrivileged(
59                new GetPropertyAction("java.net.preferIPv4Stack")));
60
61        String exclBindProp = AccessController.doPrivileged(
62                new GetPropertyAction("sun.net.useExclusiveBind", ""));
63        exclusiveBind = (exclBindProp.isEmpty())
64                ? true
65                : Boolean.parseBoolean(exclBindProp);
66    }
67
68    /**
69     * Constructs an empty instance.
70     */
71    PlainSocketImpl() {
72        if (!preferIPv4Stack) {
73            impl = new DualStackPlainSocketImpl(exclusiveBind);
74        } else {
75            impl = new TwoStacksPlainSocketImpl(exclusiveBind);
76        }
77    }
78
79    /**
80     * Constructs an instance with the given file descriptor.
81     */
82    PlainSocketImpl(FileDescriptor fd) {
83        if (!preferIPv4Stack) {
84            impl = new DualStackPlainSocketImpl(fd, exclusiveBind);
85        } else {
86            impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind);
87        }
88    }
89
90    // Override methods in SocketImpl that access impl's fields.
91
92    protected FileDescriptor getFileDescriptor() {
93        return impl.getFileDescriptor();
94    }
95
96    protected InetAddress getInetAddress() {
97        return impl.getInetAddress();
98    }
99
100    protected int getPort() {
101        return impl.getPort();
102    }
103
104    protected int getLocalPort() {
105        return impl.getLocalPort();
106    }
107
108    void setSocket(Socket soc) {
109        impl.setSocket(soc);
110    }
111
112    Socket getSocket() {
113        return impl.getSocket();
114    }
115
116    void setServerSocket(ServerSocket soc) {
117        impl.setServerSocket(soc);
118    }
119
120    ServerSocket getServerSocket() {
121        return impl.getServerSocket();
122    }
123
124    public String toString() {
125        return impl.toString();
126    }
127
128    // Override methods in AbstractPlainSocketImpl that access impl's fields.
129
130    protected synchronized void create(boolean stream) throws IOException {
131        impl.create(stream);
132
133        // set fd to delegate's fd to be compatible with older releases
134        this.fd = impl.fd;
135    }
136
137    protected void connect(String host, int port)
138        throws UnknownHostException, IOException
139    {
140        impl.connect(host, port);
141    }
142
143    protected void connect(InetAddress address, int port) throws IOException {
144        impl.connect(address, port);
145    }
146
147    protected void connect(SocketAddress address, int timeout) throws IOException {
148        impl.connect(address, timeout);
149    }
150
151    public void setOption(int opt, Object val) throws SocketException {
152        if (opt == SocketOptions.SO_REUSEPORT) {
153            // SO_REUSEPORT is not supported on Windows.
154            throw new UnsupportedOperationException("unsupported option");
155        }
156        impl.setOption(opt, val);
157    }
158
159    public Object getOption(int opt) throws SocketException {
160        if (opt == SocketOptions.SO_REUSEPORT) {
161            // SO_REUSEPORT is not supported on Windows.
162            throw new UnsupportedOperationException("unsupported option");
163        }
164        return impl.getOption(opt);
165    }
166
167    synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
168        impl.doConnect(address, port, timeout);
169    }
170
171    protected synchronized void bind(InetAddress address, int lport)
172        throws IOException
173    {
174        impl.bind(address, lport);
175    }
176
177    protected synchronized void accept(SocketImpl s) throws IOException {
178        if (s instanceof PlainSocketImpl) {
179            // pass in the real impl not the wrapper.
180            SocketImpl delegate = ((PlainSocketImpl)s).impl;
181            delegate.address = new InetAddress();
182            delegate.fd = new FileDescriptor();
183            impl.accept(delegate);
184            // set fd to delegate's fd to be compatible with older releases
185            s.fd = delegate.fd;
186        } else {
187            impl.accept(s);
188        }
189    }
190
191    void setFileDescriptor(FileDescriptor fd) {
192        impl.setFileDescriptor(fd);
193    }
194
195    void setAddress(InetAddress address) {
196        impl.setAddress(address);
197    }
198
199    void setPort(int port) {
200        impl.setPort(port);
201    }
202
203    void setLocalPort(int localPort) {
204        impl.setLocalPort(localPort);
205    }
206
207    protected synchronized InputStream getInputStream() throws IOException {
208        return impl.getInputStream();
209    }
210
211    void setInputStream(SocketInputStream in) {
212        impl.setInputStream(in);
213    }
214
215    protected synchronized OutputStream getOutputStream() throws IOException {
216        return impl.getOutputStream();
217    }
218
219    protected void close() throws IOException {
220        try {
221            impl.close();
222        } finally {
223            // set fd to delegate's fd to be compatible with older releases
224            this.fd = null;
225        }
226    }
227
228    void reset() throws IOException {
229        try {
230            impl.reset();
231        } finally {
232            // set fd to delegate's fd to be compatible with older releases
233            this.fd = null;
234        }
235    }
236
237    protected void shutdownInput() throws IOException {
238        impl.shutdownInput();
239    }
240
241    protected void shutdownOutput() throws IOException {
242        impl.shutdownOutput();
243    }
244
245    protected void sendUrgentData(int data) throws IOException {
246        impl.sendUrgentData(data);
247    }
248
249    FileDescriptor acquireFD() {
250        return impl.acquireFD();
251    }
252
253    void releaseFD() {
254        impl.releaseFD();
255    }
256
257    public boolean isConnectionReset() {
258        return impl.isConnectionReset();
259    }
260
261    public boolean isConnectionResetPending() {
262        return impl.isConnectionResetPending();
263    }
264
265    public void setConnectionReset() {
266        impl.setConnectionReset();
267    }
268
269    public void setConnectionResetPending() {
270        impl.setConnectionResetPending();
271    }
272
273    public boolean isClosedOrPending() {
274        return impl.isClosedOrPending();
275    }
276
277    public int getTimeout() {
278        return impl.getTimeout();
279    }
280
281    // Override methods in AbstractPlainSocketImpl that need to be implemented.
282
283    void socketCreate(boolean isServer) throws IOException {
284        impl.socketCreate(isServer);
285    }
286
287    void socketConnect(InetAddress address, int port, int timeout)
288        throws IOException {
289        impl.socketConnect(address, port, timeout);
290    }
291
292    void socketBind(InetAddress address, int port)
293        throws IOException {
294        impl.socketBind(address, port);
295    }
296
297    void socketListen(int count) throws IOException {
298        impl.socketListen(count);
299    }
300
301    void socketAccept(SocketImpl s) throws IOException {
302        impl.socketAccept(s);
303    }
304
305    int socketAvailable() throws IOException {
306        return impl.socketAvailable();
307    }
308
309    void socketClose0(boolean useDeferredClose) throws IOException {
310        impl.socketClose0(useDeferredClose);
311    }
312
313    void socketShutdown(int howto) throws IOException {
314        impl.socketShutdown(howto);
315    }
316
317    void socketSetOption(int cmd, boolean on, Object value)
318        throws SocketException {
319        if (cmd == SocketOptions.SO_REUSEPORT) {
320            // SO_REUSEPORT is not supported on Windows.
321            throw new UnsupportedOperationException("unsupported option");
322        }
323        impl.socketSetOption(cmd, on, value);
324    }
325
326    int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
327        if (opt == SocketOptions.SO_REUSEPORT) {
328            // SO_REUSEPORT is not supported on Windows.
329            throw new UnsupportedOperationException("unsupported option");
330        }
331        return impl.socketGetOption(opt, iaContainerObj);
332    }
333
334    void socketSendUrgentData(int data) throws IOException {
335        impl.socketSendUrgentData(data);
336    }
337
338    static boolean isReusePortAvailable() {
339        // SO_REUSEPORT is not supported on Windows.
340        return false;
341    }
342}
343