• 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.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      */
LocalSocket()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      */
LocalSocket(LocalSocketImpl impl)50     /*package*/ LocalSocket(LocalSocketImpl impl) {
51         this.impl = impl;
52         this.isConnected = false;
53         this.isBound = false;
54     }
55 
56     /** {@inheritDoc} */
57     @Override
toString()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      */
implCreateIfNeeded()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      */
connect(LocalSocketAddress endpoint)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      */
bind(LocalSocketAddress bindpoint)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      */
getLocalSocketAddress()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      */
getInputStream()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      */
getOutputStream()151     public OutputStream getOutputStream() throws IOException {
152         implCreateIfNeeded();
153         return impl.getOutputStream();
154     }
155 
156     /**
157      * Closes the socket.
158      *
159      * @throws IOException
160      */
close()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      */
shutdownInput()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      */
shutdownOutput()181     public void shutdownOutput() throws IOException {
182         implCreateIfNeeded();
183         impl.shutdownOutput();
184     }
185 
setReceiveBufferSize(int size)186     public void setReceiveBufferSize(int size) throws IOException {
187         impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
188     }
189 
getReceiveBufferSize()190     public int getReceiveBufferSize() throws IOException {
191         return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
192     }
193 
setSoTimeout(int n)194     public void setSoTimeout(int n) throws IOException {
195         impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
196     }
197 
getSoTimeout()198     public int getSoTimeout() throws IOException {
199         return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
200     }
201 
setSendBufferSize(int n)202     public void setSendBufferSize(int n) throws IOException {
203         impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
204     }
205 
getSendBufferSize()206     public int getSendBufferSize() throws IOException {
207         return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
208     }
209 
210     //???SEC
getRemoteSocketAddress()211     public LocalSocketAddress getRemoteSocketAddress() {
212         throw new UnsupportedOperationException();
213     }
214 
215     //???SEC
isConnected()216     public synchronized boolean isConnected() {
217         return isConnected;
218     }
219 
220     //???SEC
isClosed()221     public boolean isClosed() {
222         throw new UnsupportedOperationException();
223     }
224 
225     //???SEC
isBound()226     public synchronized boolean isBound() {
227         return isBound;
228     }
229 
230     //???SEC
isOutputShutdown()231     public boolean isOutputShutdown() {
232         throw new UnsupportedOperationException();
233     }
234 
235     //???SEC
isInputShutdown()236     public boolean isInputShutdown() {
237         throw new UnsupportedOperationException();
238     }
239 
240     //???SEC
connect(LocalSocketAddress endpoint, int timeout)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      */
setFileDescriptorsForSend(FileDescriptor[] fds)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      */
getAncillaryFileDescriptors()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      */
getPeerCredentials()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      */
getFileDescriptor()288     public FileDescriptor getFileDescriptor() {
289         return impl.getFileDescriptor();
290     }
291 }
292