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