Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      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
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     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.
     15  */
     16 
     17 package android.net;
     18 
     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;
     25 
     26 /**
     27  * Creates a (non-server) socket in the UNIX-domain namespace. The interface
     28  * here is not entirely unlike that of java.net.Socket
     29  */
     30 public class LocalSocket implements Closeable {
     31 
     32     private LocalSocketImpl impl;
     33     private volatile boolean implCreated;
     34     private LocalSocketAddress localAddress;
     35     private boolean isBound;
     36     private boolean isConnected;
     37 
     38     /**
     39      * Creates a AF_LOCAL/UNIX domain stream socket.
     40      */
     41     public LocalSocket() {
     42         this(new LocalSocketImpl());
     43         isBound = false;
     44         isConnected = false;
     45     }
     46     /**
     47      * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
     48      * @hide
     49      */
     50     public LocalSocket(FileDescriptor fd) throws IOException {
     51         this(new LocalSocketImpl(fd));
     52         isBound = true;
     53         isConnected = true;
     54     }
     55 
     56     /**
     57      * for use with AndroidServerSocket
     58      * @param impl a SocketImpl
     59      */
     60     /*package*/ LocalSocket(LocalSocketImpl impl) {
     61         this.impl = impl;
     62         this.isConnected = false;
     63         this.isBound = false;
     64     }
     65 
     66     /** {@inheritDoc} */
     67     @Override
     68     public String toString() {
     69         return super.toString() + " impl:" + impl;
     70     }
     71 
     72     /**
     73      * It's difficult to discern from the spec when impl.create() should be
     74      * called, but it seems like a reasonable rule is "as soon as possible,
     75      * but not in a context where IOException cannot be thrown"
     76      *
     77      * @throws IOException from SocketImpl.create()
     78      */
     79     private void implCreateIfNeeded() throws IOException {
     80         if (!implCreated) {
     81             synchronized (this) {
     82                 if (!implCreated) {
     83                     try {
     84                         impl.create(true);
     85                     } finally {
     86                         implCreated = true;
     87                     }
     88                 }
     89             }
     90         }
     91     }
     92 
     93     /**
     94      * Connects this socket to an endpoint. May only be called on an instance
     95      * that has not yet been connected.
     96      *
     97      * @param endpoint endpoint address
     98      * @throws IOException if socket is in invalid state or the address does
     99      * not exist.
    100      */
    101     public void connect(LocalSocketAddress endpoint) throws IOException {
    102         synchronized (this) {
    103             if (isConnected) {
    104                 throw new IOException("already connected");
    105             }
    106 
    107             implCreateIfNeeded();
    108             impl.connect(endpoint, 0);
    109             isConnected = true;
    110             isBound = true;
    111         }
    112     }
    113 
    114     /**
    115      * Binds this socket to an endpoint name. May only be called on an instance
    116      * that has not yet been bound.
    117      *
    118      * @param bindpoint endpoint address
    119      * @throws IOException
    120      */
    121     public void bind(LocalSocketAddress bindpoint) throws IOException {
    122         implCreateIfNeeded();
    123 
    124         synchronized (this) {
    125             if (isBound) {
    126                 throw new IOException("already bound");
    127             }
    128 
    129             localAddress = bindpoint;
    130             impl.bind(localAddress);
    131             isBound = true;
    132         }
    133     }
    134 
    135     /**
    136      * Retrieves the name that this socket is bound to, if any.
    137      *
    138      * @return Local address or null if anonymous
    139      */
    140     public LocalSocketAddress getLocalSocketAddress() {
    141         return localAddress;
    142     }
    143 
    144     /**
    145      * Retrieves the input stream for this instance.
    146      *
    147      * @return input stream
    148      * @throws IOException if socket has been closed or cannot be created.
    149      */
    150     public InputStream getInputStream() throws IOException {
    151         implCreateIfNeeded();
    152         return impl.getInputStream();
    153     }
    154 
    155     /**
    156      * Retrieves the output stream for this instance.
    157      *
    158      * @return output stream
    159      * @throws IOException if socket has been closed or cannot be created.
    160      */
    161     public OutputStream getOutputStream() throws IOException {
    162         implCreateIfNeeded();
    163         return impl.getOutputStream();
    164     }
    165 
    166     /**
    167      * Closes the socket.
    168      *
    169      * @throws IOException
    170      */
    171     @Override
    172     public void close() throws IOException {
    173         implCreateIfNeeded();
    174         impl.close();
    175     }
    176 
    177     /**
    178      * Shuts down the input side of the socket.
    179      *
    180      * @throws IOException
    181      */
    182     public void shutdownInput() throws IOException {
    183         implCreateIfNeeded();
    184         impl.shutdownInput();
    185     }
    186 
    187     /**
    188      * Shuts down the output side of the socket.
    189      *
    190      * @throws IOException
    191      */
    192     public void shutdownOutput() throws IOException {
    193         implCreateIfNeeded();
    194         impl.shutdownOutput();
    195     }
    196 
    197     public void setReceiveBufferSize(int size) throws IOException {
    198         impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
    199     }
    200 
    201     public int getReceiveBufferSize() throws IOException {
    202         return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
    203     }
    204 
    205     public void setSoTimeout(int n) throws IOException {
    206         impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
    207     }
    208 
    209     public int getSoTimeout() throws IOException {
    210         return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
    211     }
    212 
    213     public void setSendBufferSize(int n) throws IOException {
    214         impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
    215     }
    216 
    217     public int getSendBufferSize() throws IOException {
    218         return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
    219     }
    220 
    221     //???SEC
    222     public LocalSocketAddress getRemoteSocketAddress() {
    223         throw new UnsupportedOperationException();
    224     }
    225 
    226     //???SEC
    227     public synchronized boolean isConnected() {
    228         return isConnected;
    229     }
    230 
    231     //???SEC
    232     public boolean isClosed() {
    233         throw new UnsupportedOperationException();
    234     }
    235 
    236     //???SEC
    237     public synchronized boolean isBound() {
    238         return isBound;
    239     }
    240 
    241     //???SEC
    242     public boolean isOutputShutdown() {
    243         throw new UnsupportedOperationException();
    244     }
    245 
    246     //???SEC
    247     public boolean isInputShutdown() {
    248         throw new UnsupportedOperationException();
    249     }
    250 
    251     //???SEC
    252     public void connect(LocalSocketAddress endpoint, int timeout)
    253             throws IOException {
    254         throw new UnsupportedOperationException();
    255     }
    256 
    257     /**
    258      * Enqueues a set of file descriptors to send to the peer. The queue
    259      * is one deep. The file descriptors will be sent with the next write
    260      * of normal data, and will be delivered in a single ancillary message.
    261      * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine.
    262      *
    263      * @param fds non-null; file descriptors to send.
    264      */
    265     public void setFileDescriptorsForSend(FileDescriptor[] fds) {
    266         impl.setFileDescriptorsForSend(fds);
    267     }
    268 
    269     /**
    270      * Retrieves a set of file descriptors that a peer has sent through
    271      * an ancillary message. This method retrieves the most recent set sent,
    272      * and then returns null until a new set arrives.
    273      * File descriptors may only be passed along with regular data, so this
    274      * method can only return a non-null after a read operation.
    275      *
    276      * @return null or file descriptor array
    277      * @throws IOException
    278      */
    279     public FileDescriptor[] getAncillaryFileDescriptors() throws IOException {
    280         return impl.getAncillaryFileDescriptors();
    281     }
    282 
    283     /**
    284      * Retrieves the credentials of this socket's peer. Only valid on
    285      * connected sockets.
    286      *
    287      * @return non-null; peer credentials
    288      * @throws IOException
    289      */
    290     public Credentials getPeerCredentials() throws IOException {
    291         return impl.getPeerCredentials();
    292     }
    293 
    294     /**
    295      * Returns file descriptor or null if not yet open/already closed
    296      *
    297      * @return fd or null
    298      */
    299     public FileDescriptor getFileDescriptor() {
    300         return impl.getFileDescriptor();
    301     }
    302 }
    303