• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
LocalSocket()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      */
LocalSocket(FileDescriptor fd)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      */
LocalSocket(LocalSocketImpl impl)60     /*package*/ LocalSocket(LocalSocketImpl impl) {
61         this.impl = impl;
62         this.isConnected = false;
63         this.isBound = false;
64     }
65 
66     /** {@inheritDoc} */
67     @Override
toString()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      */
implCreateIfNeeded()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      */
connect(LocalSocketAddress endpoint)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      */
bind(LocalSocketAddress bindpoint)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      */
getLocalSocketAddress()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      */
getInputStream()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      */
getOutputStream()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
close()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      */
shutdownInput()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      */
shutdownOutput()192     public void shutdownOutput() throws IOException {
193         implCreateIfNeeded();
194         impl.shutdownOutput();
195     }
196 
setReceiveBufferSize(int size)197     public void setReceiveBufferSize(int size) throws IOException {
198         impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
199     }
200 
getReceiveBufferSize()201     public int getReceiveBufferSize() throws IOException {
202         return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
203     }
204 
setSoTimeout(int n)205     public void setSoTimeout(int n) throws IOException {
206         impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
207     }
208 
getSoTimeout()209     public int getSoTimeout() throws IOException {
210         return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
211     }
212 
setSendBufferSize(int n)213     public void setSendBufferSize(int n) throws IOException {
214         impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
215     }
216 
getSendBufferSize()217     public int getSendBufferSize() throws IOException {
218         return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
219     }
220 
221     //???SEC
getRemoteSocketAddress()222     public LocalSocketAddress getRemoteSocketAddress() {
223         throw new UnsupportedOperationException();
224     }
225 
226     //???SEC
isConnected()227     public synchronized boolean isConnected() {
228         return isConnected;
229     }
230 
231     //???SEC
isClosed()232     public boolean isClosed() {
233         throw new UnsupportedOperationException();
234     }
235 
236     //???SEC
isBound()237     public synchronized boolean isBound() {
238         return isBound;
239     }
240 
241     //???SEC
isOutputShutdown()242     public boolean isOutputShutdown() {
243         throw new UnsupportedOperationException();
244     }
245 
246     //???SEC
isInputShutdown()247     public boolean isInputShutdown() {
248         throw new UnsupportedOperationException();
249     }
250 
251     //???SEC
connect(LocalSocketAddress endpoint, int timeout)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      */
setFileDescriptorsForSend(FileDescriptor[] fds)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      */
getAncillaryFileDescriptors()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      */
getPeerCredentials()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      */
getFileDescriptor()299     public FileDescriptor getFileDescriptor() {
300         return impl.getFileDescriptor();
301     }
302 }
303