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