blob: 14a80948b7977615341891ae178675ed6a0c21d6 [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
28 * here is not entirely unlike that of java.net.Socket
29 */
Jeff Sharkey065b2992012-08-05 14:16:48 -070030public class LocalSocket implements Closeable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031
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 */
41 public LocalSocket() {
42 this(new LocalSocketImpl());
43 isBound = false;
44 isConnected = false;
45 }
zzy3b147b72012-04-03 19:48:32 -070046 /**
47 * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
48 * @hide
49 */
50 public LocalSocket(FileDescriptor fd) throws IOException {
51 this(new LocalSocketImpl(fd));
52 isBound = true;
53 isConnected = true;
54 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56 /**
57 * for use with AndroidServerSocket
58 * @param impl a SocketImpl
59 */
60 /*package*/ LocalSocket(LocalSocketImpl impl) {
61 this.impl = impl;
62 this.isConnected = false;
63 this.isBound = false;
64 }
65
66 /** {@inheritDoc} */
67 @Override
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 */
79 private void implCreateIfNeeded() throws IOException {
80 if (!implCreated) {
81 synchronized (this) {
82 if (!implCreated) {
Jesse Wilsonc59a6622010-09-21 10:26:57 -070083 try {
84 impl.create(true);
85 } finally {
86 implCreated = true;
87 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 }
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 */
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 */
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 */
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 */
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 */
161 public OutputStream getOutputStream() throws IOException {
162 implCreateIfNeeded();
163 return impl.getOutputStream();
164 }
165
166 /**
167 * Closes the socket.
168 *
169 * @throws IOException
170 */
Jeff Sharkey065b2992012-08-05 14:16:48 -0700171 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 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 */
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 */
192 public void shutdownOutput() throws IOException {
193 implCreateIfNeeded();
194 impl.shutdownOutput();
195 }
196
197 public void setReceiveBufferSize(int size) throws IOException {
198 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
199 }
200
201 public int getReceiveBufferSize() throws IOException {
202 return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
203 }
204
205 public void setSoTimeout(int n) throws IOException {
206 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
207 }
208
209 public int getSoTimeout() throws IOException {
210 return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
211 }
212
213 public void setSendBufferSize(int n) throws IOException {
214 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
215 }
216
217 public int getSendBufferSize() throws IOException {
218 return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
219 }
220
221 //???SEC
222 public LocalSocketAddress getRemoteSocketAddress() {
223 throw new UnsupportedOperationException();
224 }
225
226 //???SEC
227 public synchronized boolean isConnected() {
228 return isConnected;
229 }
230
231 //???SEC
232 public boolean isClosed() {
233 throw new UnsupportedOperationException();
234 }
235
236 //???SEC
237 public synchronized boolean isBound() {
238 return isBound;
239 }
240
241 //???SEC
242 public boolean isOutputShutdown() {
243 throw new UnsupportedOperationException();
244 }
245
246 //???SEC
247 public boolean isInputShutdown() {
248 throw new UnsupportedOperationException();
249 }
250
251 //???SEC
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 */
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 */
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 */
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 */
299 public FileDescriptor getFileDescriptor() {
300 return impl.getFileDescriptor();
301 }
302}