2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 import java.io.Closeable;
20 import java.io.FileDescriptor;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.net.SocketOptions;
27 * Creates a (non-server) socket in the UNIX-domain namespace. The interface
28 * here is not entirely unlike that of java.net.Socket. This class and the streams
29 * returned from it may be used from multiple threads.
31 public class LocalSocket implements Closeable {
33 private final LocalSocketImpl impl;
34 private volatile boolean implCreated;
35 private LocalSocketAddress localAddress;
36 private boolean isBound;
37 private boolean isConnected;
38 private final int sockType;
40 /** unknown socket type (used for constructor with existing file descriptor) */
41 /* package */ static final int SOCKET_UNKNOWN = 0;
42 /** Datagram socket type */
43 public static final int SOCKET_DGRAM = 1;
44 /** Stream socket type */
45 public static final int SOCKET_STREAM = 2;
46 /** Sequential packet socket type */
47 public static final int SOCKET_SEQPACKET = 3;
50 * Creates a AF_LOCAL/UNIX domain stream socket.
52 public LocalSocket() {
57 * Creates a AF_LOCAL/UNIX domain stream socket with given socket type
59 * @param sockType either {@link #SOCKET_DGRAM}, {@link #SOCKET_STREAM}
60 * or {@link #SOCKET_SEQPACKET}
62 public LocalSocket(int sockType) {
63 this(new LocalSocketImpl(), sockType);
69 * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
72 public LocalSocket(FileDescriptor fd) throws IOException {
73 this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
79 * for use with AndroidServerSocket
80 * @param impl a SocketImpl
82 /*package*/ LocalSocket(LocalSocketImpl impl, int sockType) {
84 this.sockType = sockType;
85 this.isConnected = false;
91 public String toString() {
92 return super.toString() + " impl:" + impl;
96 * It's difficult to discern from the spec when impl.create() should be
97 * called, but it seems like a reasonable rule is "as soon as possible,
98 * but not in a context where IOException cannot be thrown"
100 * @throws IOException from SocketImpl.create()
102 private void implCreateIfNeeded() throws IOException {
104 synchronized (this) {
107 impl.create(sockType);
117 * Connects this socket to an endpoint. May only be called on an instance
118 * that has not yet been connected.
120 * @param endpoint endpoint address
121 * @throws IOException if socket is in invalid state or the address does
124 public void connect(LocalSocketAddress endpoint) throws IOException {
125 synchronized (this) {
127 throw new IOException("already connected");
130 implCreateIfNeeded();
131 impl.connect(endpoint, 0);
138 * Binds this socket to an endpoint name. May only be called on an instance
139 * that has not yet been bound.
141 * @param bindpoint endpoint address
142 * @throws IOException
144 public void bind(LocalSocketAddress bindpoint) throws IOException {
145 implCreateIfNeeded();
147 synchronized (this) {
149 throw new IOException("already bound");
152 localAddress = bindpoint;
153 impl.bind(localAddress);
159 * Retrieves the name that this socket is bound to, if any.
161 * @return Local address or null if anonymous
163 public LocalSocketAddress getLocalSocketAddress() {
168 * Retrieves the input stream for this instance.
170 * @return input stream
171 * @throws IOException if socket has been closed or cannot be created.
173 public InputStream getInputStream() throws IOException {
174 implCreateIfNeeded();
175 return impl.getInputStream();
179 * Retrieves the output stream for this instance.
181 * @return output stream
182 * @throws IOException if socket has been closed or cannot be created.
184 public OutputStream getOutputStream() throws IOException {
185 implCreateIfNeeded();
186 return impl.getOutputStream();
192 * @throws IOException
195 public void close() throws IOException {
196 implCreateIfNeeded();
201 * Shuts down the input side of the socket.
203 * @throws IOException
205 public void shutdownInput() throws IOException {
206 implCreateIfNeeded();
207 impl.shutdownInput();
211 * Shuts down the output side of the socket.
213 * @throws IOException
215 public void shutdownOutput() throws IOException {
216 implCreateIfNeeded();
217 impl.shutdownOutput();
220 public void setReceiveBufferSize(int size) throws IOException {
221 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
224 public int getReceiveBufferSize() throws IOException {
225 return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
228 public void setSoTimeout(int n) throws IOException {
229 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
232 public int getSoTimeout() throws IOException {
233 return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
236 public void setSendBufferSize(int n) throws IOException {
237 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
240 public int getSendBufferSize() throws IOException {
241 return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
245 public LocalSocketAddress getRemoteSocketAddress() {
246 throw new UnsupportedOperationException();
250 public synchronized boolean isConnected() {
255 public boolean isClosed() {
256 throw new UnsupportedOperationException();
260 public synchronized boolean isBound() {
265 public boolean isOutputShutdown() {
266 throw new UnsupportedOperationException();
270 public boolean isInputShutdown() {
271 throw new UnsupportedOperationException();
275 public void connect(LocalSocketAddress endpoint, int timeout)
277 throw new UnsupportedOperationException();
281 * Enqueues a set of file descriptors to send to the peer. The queue
282 * is one deep. The file descriptors will be sent with the next write
283 * of normal data, and will be delivered in a single ancillary message.
284 * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine.
286 * @param fds non-null; file descriptors to send.
288 public void setFileDescriptorsForSend(FileDescriptor[] fds) {
289 impl.setFileDescriptorsForSend(fds);
293 * Retrieves a set of file descriptors that a peer has sent through
294 * an ancillary message. This method retrieves the most recent set sent,
295 * and then returns null until a new set arrives.
296 * File descriptors may only be passed along with regular data, so this
297 * method can only return a non-null after a read operation.
299 * @return null or file descriptor array
300 * @throws IOException
302 public FileDescriptor[] getAncillaryFileDescriptors() throws IOException {
303 return impl.getAncillaryFileDescriptors();
307 * Retrieves the credentials of this socket's peer. Only valid on
310 * @return non-null; peer credentials
311 * @throws IOException
313 public Credentials getPeerCredentials() throws IOException {
314 return impl.getPeerCredentials();
318 * Returns file descriptor or null if not yet open/already closed
322 public FileDescriptor getFileDescriptor() {
323 return impl.getFileDescriptor();