blob: e14facb1abb55fcbf9af72afc2a8d7dc662e2a53 [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
Jeff Sharkey065b2992012-08-05 14:16:48 -070019import java.io.Closeable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import java.io.FileDescriptor;
21import java.io.IOException;
22import java.io.InputStream;
23import java.io.OutputStream;
24import java.net.SocketOptions;
25
26/**
27 * Creates a (non-server) socket in the UNIX-domain namespace. The interface
Neil Fullerbf0dc0f2015-11-24 18:19:06 +000028 * here is not entirely unlike that of java.net.Socket. This class and the streams
29 * returned from it may be used from multiple threads.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030 */
Jeff Sharkey065b2992012-08-05 14:16:48 -070031public class LocalSocket implements Closeable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
Ian Rogersd8e34a62014-08-27 16:32:57 -070033 private final LocalSocketImpl impl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034 private volatile boolean implCreated;
35 private LocalSocketAddress localAddress;
36 private boolean isBound;
37 private boolean isConnected;
Mike Lockwoode7d309a2013-07-16 11:36:22 -070038 private final int sockType;
39
40 /** unknown socket type (used for constructor with existing file descriptor) */
41 /* package */ static final int SOCKET_UNKNOWN = 0;
42 /** Datagram socket type */
43 public static final int SOCKET_DGRAM = 1;
44 /** Stream socket type */
45 public static final int SOCKET_STREAM = 2;
46 /** Sequential packet socket type */
47 public static final int SOCKET_SEQPACKET = 3;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
49 /**
50 * Creates a AF_LOCAL/UNIX domain stream socket.
51 */
52 public LocalSocket() {
Mike Lockwoode7d309a2013-07-16 11:36:22 -070053 this(SOCKET_STREAM);
54 }
55
56 /**
57 * Creates a AF_LOCAL/UNIX domain stream socket with given socket type
58 *
59 * @param sockType either {@link #SOCKET_DGRAM}, {@link #SOCKET_STREAM}
60 * or {@link #SOCKET_SEQPACKET}
61 */
62 public LocalSocket(int sockType) {
63 this(new LocalSocketImpl(), sockType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 isBound = false;
65 isConnected = false;
66 }
Mike Lockwoode7d309a2013-07-16 11:36:22 -070067
zzy3b147b72012-04-03 19:48:32 -070068 /**
69 * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
70 * @hide
71 */
72 public LocalSocket(FileDescriptor fd) throws IOException {
Mike Lockwoode7d309a2013-07-16 11:36:22 -070073 this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
zzy3b147b72012-04-03 19:48:32 -070074 isBound = true;
75 isConnected = true;
76 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077
78 /**
79 * for use with AndroidServerSocket
80 * @param impl a SocketImpl
81 */
Mike Lockwoode7d309a2013-07-16 11:36:22 -070082 /*package*/ LocalSocket(LocalSocketImpl impl, int sockType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 this.impl = impl;
Mike Lockwoode7d309a2013-07-16 11:36:22 -070084 this.sockType = sockType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 this.isConnected = false;
86 this.isBound = false;
87 }
88
89 /** {@inheritDoc} */
90 @Override
91 public String toString() {
92 return super.toString() + " impl:" + impl;
93 }
94
95 /**
96 * It's difficult to discern from the spec when impl.create() should be
97 * called, but it seems like a reasonable rule is "as soon as possible,
98 * but not in a context where IOException cannot be thrown"
99 *
100 * @throws IOException from SocketImpl.create()
101 */
102 private void implCreateIfNeeded() throws IOException {
103 if (!implCreated) {
104 synchronized (this) {
105 if (!implCreated) {
Jesse Wilsonc59a6622010-09-21 10:26:57 -0700106 try {
Mike Lockwoode7d309a2013-07-16 11:36:22 -0700107 impl.create(sockType);
Jesse Wilsonc59a6622010-09-21 10:26:57 -0700108 } finally {
109 implCreated = true;
110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 }
112 }
113 }
114 }
115
116 /**
117 * Connects this socket to an endpoint. May only be called on an instance
118 * that has not yet been connected.
119 *
120 * @param endpoint endpoint address
121 * @throws IOException if socket is in invalid state or the address does
122 * not exist.
123 */
124 public void connect(LocalSocketAddress endpoint) throws IOException {
125 synchronized (this) {
126 if (isConnected) {
127 throw new IOException("already connected");
128 }
129
130 implCreateIfNeeded();
131 impl.connect(endpoint, 0);
132 isConnected = true;
133 isBound = true;
134 }
135 }
136
137 /**
138 * Binds this socket to an endpoint name. May only be called on an instance
139 * that has not yet been bound.
140 *
141 * @param bindpoint endpoint address
142 * @throws IOException
143 */
144 public void bind(LocalSocketAddress bindpoint) throws IOException {
145 implCreateIfNeeded();
146
147 synchronized (this) {
148 if (isBound) {
149 throw new IOException("already bound");
150 }
151
152 localAddress = bindpoint;
153 impl.bind(localAddress);
154 isBound = true;
155 }
156 }
157
158 /**
159 * Retrieves the name that this socket is bound to, if any.
160 *
161 * @return Local address or null if anonymous
162 */
163 public LocalSocketAddress getLocalSocketAddress() {
164 return localAddress;
165 }
166
167 /**
168 * Retrieves the input stream for this instance.
169 *
170 * @return input stream
171 * @throws IOException if socket has been closed or cannot be created.
172 */
173 public InputStream getInputStream() throws IOException {
174 implCreateIfNeeded();
175 return impl.getInputStream();
176 }
177
178 /**
179 * Retrieves the output stream for this instance.
180 *
181 * @return output stream
182 * @throws IOException if socket has been closed or cannot be created.
183 */
184 public OutputStream getOutputStream() throws IOException {
185 implCreateIfNeeded();
186 return impl.getOutputStream();
187 }
188
189 /**
190 * Closes the socket.
191 *
192 * @throws IOException
193 */
Jeff Sharkey065b2992012-08-05 14:16:48 -0700194 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 public void close() throws IOException {
196 implCreateIfNeeded();
197 impl.close();
198 }
199
200 /**
201 * Shuts down the input side of the socket.
202 *
203 * @throws IOException
204 */
205 public void shutdownInput() throws IOException {
206 implCreateIfNeeded();
207 impl.shutdownInput();
208 }
209
210 /**
211 * Shuts down the output side of the socket.
212 *
213 * @throws IOException
214 */
215 public void shutdownOutput() throws IOException {
216 implCreateIfNeeded();
217 impl.shutdownOutput();
218 }
219
220 public void setReceiveBufferSize(int size) throws IOException {
221 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
222 }
223
224 public int getReceiveBufferSize() throws IOException {
225 return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
226 }
227
228 public void setSoTimeout(int n) throws IOException {
229 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
230 }
231
232 public int getSoTimeout() throws IOException {
233 return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
234 }
235
236 public void setSendBufferSize(int n) throws IOException {
237 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
238 }
239
240 public int getSendBufferSize() throws IOException {
241 return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
242 }
243
244 //???SEC
245 public LocalSocketAddress getRemoteSocketAddress() {
246 throw new UnsupportedOperationException();
247 }
248
249 //???SEC
250 public synchronized boolean isConnected() {
251 return isConnected;
252 }
253
254 //???SEC
255 public boolean isClosed() {
256 throw new UnsupportedOperationException();
257 }
258
259 //???SEC
260 public synchronized boolean isBound() {
261 return isBound;
262 }
263
264 //???SEC
265 public boolean isOutputShutdown() {
266 throw new UnsupportedOperationException();
267 }
268
269 //???SEC
270 public boolean isInputShutdown() {
271 throw new UnsupportedOperationException();
272 }
273
274 //???SEC
275 public void connect(LocalSocketAddress endpoint, int timeout)
276 throws IOException {
277 throw new UnsupportedOperationException();
278 }
279
280 /**
281 * Enqueues a set of file descriptors to send to the peer. The queue
282 * is one deep. The file descriptors will be sent with the next write
283 * of normal data, and will be delivered in a single ancillary message.
284 * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine.
285 *
286 * @param fds non-null; file descriptors to send.
287 */
288 public void setFileDescriptorsForSend(FileDescriptor[] fds) {
289 impl.setFileDescriptorsForSend(fds);
290 }
291
292 /**
293 * Retrieves a set of file descriptors that a peer has sent through
294 * an ancillary message. This method retrieves the most recent set sent,
295 * and then returns null until a new set arrives.
296 * File descriptors may only be passed along with regular data, so this
297 * method can only return a non-null after a read operation.
298 *
299 * @return null or file descriptor array
300 * @throws IOException
301 */
302 public FileDescriptor[] getAncillaryFileDescriptors() throws IOException {
303 return impl.getAncillaryFileDescriptors();
304 }
305
306 /**
307 * Retrieves the credentials of this socket's peer. Only valid on
308 * connected sockets.
309 *
310 * @return non-null; peer credentials
311 * @throws IOException
312 */
313 public Credentials getPeerCredentials() throws IOException {
314 return impl.getPeerCredentials();
315 }
316
317 /**
318 * Returns file descriptor or null if not yet open/already closed
319 *
320 * @return fd or null
321 */
322 public FileDescriptor getFileDescriptor() {
323 return impl.getFileDescriptor();
324 }
325}