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