1 /*
2  * Copyright (c) 2000, 2013, 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.channels.*;
31 
32 
33 // Make a server-socket channel look like a server socket.
34 //
35 // The methods in this class are defined in exactly the same order as in
36 // java.net.ServerSocket so as to simplify tracking future changes to that
37 // class.
38 //
39 
40 public class ServerSocketAdaptor                        // package-private
41     extends ServerSocket
42 {
43 
44     // The channel being adapted
45     private final ServerSocketChannelImpl ssc;
46 
47     // Timeout "option" value for accepts
48     private volatile int timeout = 0;
49 
create(ServerSocketChannelImpl ssc)50     public static ServerSocket create(ServerSocketChannelImpl ssc) {
51         try {
52             return new ServerSocketAdaptor(ssc);
53         } catch (IOException x) {
54             throw new Error(x);
55         }
56     }
57 
58     // ## super will create a useless impl
ServerSocketAdaptor(ServerSocketChannelImpl ssc)59     private ServerSocketAdaptor(ServerSocketChannelImpl ssc)
60         throws IOException
61     {
62         this.ssc = ssc;
63     }
64 
65 
bind(SocketAddress local)66     public void bind(SocketAddress local) throws IOException {
67         bind(local, 50);
68     }
69 
bind(SocketAddress local, int backlog)70     public void bind(SocketAddress local, int backlog) throws IOException {
71         if (local == null)
72             local = new InetSocketAddress(0);
73         try {
74             ssc.bind(local, backlog);
75         } catch (Exception x) {
76             Net.translateException(x);
77         }
78     }
79 
getInetAddress()80     public InetAddress getInetAddress() {
81         if (!ssc.isBound())
82             return null;
83         return Net.getRevealedLocalAddress(ssc.localAddress()).getAddress();
84 
85     }
86 
getLocalPort()87     public int getLocalPort() {
88         if (!ssc.isBound())
89             return -1;
90         return Net.asInetSocketAddress(ssc.localAddress()).getPort();
91     }
92 
93 
accept()94     public Socket accept() throws IOException {
95         synchronized (ssc.blockingLock()) {
96             if (!ssc.isBound())
97                 throw new IllegalBlockingModeException();
98             try {
99                 if (timeout == 0) {
100                     SocketChannel sc = ssc.accept();
101                     if (sc == null && !ssc.isBlocking())
102                         throw new IllegalBlockingModeException();
103                     return sc.socket();
104                 }
105 
106                 ssc.configureBlocking(false);
107                 try {
108                     SocketChannel sc;
109                     if ((sc = ssc.accept()) != null)
110                         return sc.socket();
111                     long to = timeout;
112                     for (;;) {
113                         if (!ssc.isOpen())
114                             throw new ClosedChannelException();
115                         long st = System.currentTimeMillis();
116                         int result = ssc.poll(Net.POLLIN, to);
117                         if (result > 0 && ((sc = ssc.accept()) != null))
118                             return sc.socket();
119                         to -= System.currentTimeMillis() - st;
120                         if (to <= 0)
121                             throw new SocketTimeoutException();
122                     }
123                 } finally {
124                     if (ssc.isOpen())
125                         ssc.configureBlocking(true);
126                 }
127 
128             } catch (Exception x) {
129                 Net.translateException(x);
130                 assert false;
131                 return null;            // Never happens
132             }
133         }
134     }
135 
close()136     public void close() throws IOException {
137         ssc.close();
138     }
139 
getChannel()140     public ServerSocketChannel getChannel() {
141         return ssc;
142     }
143 
isBound()144     public boolean isBound() {
145         return ssc.isBound();
146     }
147 
isClosed()148     public boolean isClosed() {
149         return !ssc.isOpen();
150     }
151 
setSoTimeout(int timeout)152     public void setSoTimeout(int timeout) throws SocketException {
153         this.timeout = timeout;
154     }
155 
getSoTimeout()156     public int getSoTimeout() throws SocketException {
157         return timeout;
158     }
159 
setReuseAddress(boolean on)160     public void setReuseAddress(boolean on) throws SocketException {
161         try {
162             ssc.setOption(StandardSocketOptions.SO_REUSEADDR, on);
163         } catch (IOException x) {
164             Net.translateToSocketException(x);
165         }
166     }
167 
getReuseAddress()168     public boolean getReuseAddress() throws SocketException {
169         try {
170             return ssc.getOption(StandardSocketOptions.SO_REUSEADDR).booleanValue();
171         } catch (IOException x) {
172             Net.translateToSocketException(x);
173             return false;       // Never happens
174         }
175     }
176 
toString()177     public String toString() {
178         if (!isBound())
179             return "ServerSocket[unbound]";
180         return "ServerSocket[addr=" + getInetAddress() +
181             //          ",port=" + getPort() +
182                 ",localport=" + getLocalPort()  + "]";
183     }
184 
setReceiveBufferSize(int size)185     public void setReceiveBufferSize(int size) throws SocketException {
186         // size 0 valid for ServerSocketChannel, invalid for ServerSocket
187         if (size <= 0)
188             throw new IllegalArgumentException("size cannot be 0 or negative");
189         try {
190             ssc.setOption(StandardSocketOptions.SO_RCVBUF, size);
191         } catch (IOException x) {
192             Net.translateToSocketException(x);
193         }
194     }
195 
getReceiveBufferSize()196     public int getReceiveBufferSize() throws SocketException {
197         try {
198             return ssc.getOption(StandardSocketOptions.SO_RCVBUF).intValue();
199         } catch (IOException x) {
200             Net.translateToSocketException(x);
201             return -1;          // Never happens
202         }
203     }
204 
205 }
206