19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.SocketOptions; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2534385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.ErrnoException; 2634385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.Os; 2734385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.OsConstants; 28c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fullerimport android.system.StructLinger; 29c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fullerimport android.system.StructTimeval; 30d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fullerimport android.util.MutableInt; 31e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Socket implementation used for android.net.LocalSocket and 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.net.LocalServerSocket. Supports only AF_LOCAL sockets. 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass LocalSocketImpl 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SocketInputStream fis; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SocketOutputStream fos; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object readMonitor = new Object(); 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object writeMonitor = new Object(); 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** null if closed or not yet created */ 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private FileDescriptor fd; 45118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu /** whether fd is created internally */ 46118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu private boolean mFdCreatedInternally; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // These fields are accessed by native code; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** file descriptor array received during a previous read */ 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor[] inboundFileDescriptors; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** file descriptor array that should be written during next write */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor[] outboundFileDescriptors; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An input stream for local sockets. Needed because we may 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need to read ancillary data. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class SocketInputStream extends InputStream { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int available() throws IOException { 6254d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar FileDescriptor myFd = fd; 6354d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar if (myFd == null) throw new IOException("socket closed"); 6454d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar 65d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller MutableInt avail = new MutableInt(0); 66d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller try { 67d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller Os.ioctlInt(myFd, OsConstants.FIONREAD, avail); 68d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller } catch (ErrnoException e) { 69d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller throw e.rethrowAsIOException(); 70d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller } 71d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller return avail.value; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LocalSocketImpl.this.close(); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read() throws IOException { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (readMonitor) { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor myFd = fd; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (myFd == null) throw new IOException("socket closed"); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = read_native(myFd); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read(byte[] b) throws IOException { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return read(b, 0, b.length); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read(byte[] b, int off, int len) throws IOException { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (readMonitor) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor myFd = fd; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (myFd == null) throw new IOException("socket closed"); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > b.length ) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ArrayIndexOutOfBoundsException(); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret = readba_native(b, off, len, myFd); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An output stream for local sockets. Needed because we may 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need to read ancillary data. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class SocketOutputStream extends OutputStream { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LocalSocketImpl.this.close(); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void write (byte[] b) throws IOException { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project write(b, 0, b.length); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void write (byte[] b, int off, int len) throws IOException { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (writeMonitor) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor myFd = fd; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (myFd == null) throw new IOException("socket closed"); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (off < 0 || len < 0 || (off + len) > b.length ) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new ArrayIndexOutOfBoundsException(); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writeba_native(b, off, len, myFd); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** {@inheritDoc} */ 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void write (int b) throws IOException { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (writeMonitor) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor myFd = fd; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (myFd == null) throw new IOException("socket closed"); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project write_native(b, myFd); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15771bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy 15871bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy /** 15971bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy * Wait until the data in sending queue is emptied. A polling version 16071bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy * for flush implementation. 16171bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy * @throws IOException 16271bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy * if an i/o error occurs. 16371bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy */ 16471bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy @Override 16571bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy public void flush() throws IOException { 16671bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy FileDescriptor myFd = fd; 16771bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy if (myFd == null) throw new IOException("socket closed"); 168d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller 169d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller // Loop until the output buffer is empty. 170d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller MutableInt pending = new MutableInt(0); 171d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller while (true) { 172d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller try { 173d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller // See linux/net/unix/af_unix.c 174d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller Os.ioctlInt(myFd, OsConstants.TIOCOUTQ, pending); 175d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller } catch (ErrnoException e) { 176d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller throw e.rethrowAsIOException(); 177d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller } 178d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller 179d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller if (pending.value <= 0) { 180d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller // The output buffer is empty. 181d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller break; 182d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller } 183d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller 18471bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy try { 18571bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy Thread.sleep(10); 18671bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy } catch (InterruptedException ie) { 187d2df87eb4424ec25ab5c9a8f47cb09a8f191e87fNeil Fuller break; 18871bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy } 18971bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy } 19071bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native int read_native(FileDescriptor fd) throws IOException; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native int readba_native(byte[] b, int off, int len, 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor fd) throws IOException; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void writeba_native(byte[] b, int off, int len, 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor fd) throws IOException; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void write_native(int b, FileDescriptor fd) 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void connectLocal(FileDescriptor fd, String name, 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int namespace) throws IOException; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void bindLocal(FileDescriptor fd, String name, int namespace) 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native Credentials getPeerCredentials_native( 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor fd) throws IOException; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new instance. 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /*package*/ LocalSocketImpl() 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new instance from a file descriptor representing 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a bound socket. The state of the file descriptor is not checked here 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but the caller can verify socket state by calling listen(). 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fd non-null; bound file descriptor 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /*package*/ LocalSocketImpl(FileDescriptor fd) throws IOException 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.fd = fd; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.toString() + " fd:" + fd; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a socket in the underlying OS. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 233e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood * @param sockType either {@link LocalSocket#SOCKET_DGRAM}, {@link LocalSocket#SOCKET_STREAM} 234e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood * or {@link LocalSocket#SOCKET_SEQPACKET} 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 237c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller public void create(int sockType) throws IOException { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no error if socket already created 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need this for LocalServerSocket.accept() 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 241e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood int osType; 242e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood switch (sockType) { 243e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood case LocalSocket.SOCKET_DGRAM: 244e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood osType = OsConstants.SOCK_DGRAM; 245e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood break; 246e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood case LocalSocket.SOCKET_STREAM: 247e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood osType = OsConstants.SOCK_STREAM; 248e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood break; 249e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood case LocalSocket.SOCKET_SEQPACKET: 250e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood osType = OsConstants.SOCK_SEQPACKET; 251e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood break; 252e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood default: 253e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood throw new IllegalStateException("unknown sockType"); 254e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood } 255e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood try { 25634385d352da19805ae948215e2edbeedd16b7941Elliott Hughes fd = Os.socket(OsConstants.AF_UNIX, osType, 0); 257118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu mFdCreatedInternally = true; 258e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood } catch (ErrnoException e) { 259e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood e.rethrowAsIOException(); 260e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Closes the socket. 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (LocalSocketImpl.this) { 271118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu if ((fd == null) || (mFdCreatedInternally == false)) { 272118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu fd = null; 273118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu return; 274118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu } 275e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood try { 27634385d352da19805ae948215e2edbeedd16b7941Elliott Hughes Os.close(fd); 277e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood } catch (ErrnoException e) { 278e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood e.rethrowAsIOException(); 279e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = null; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** note timeout presently ignored */ 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void connect(LocalSocketAddress address, int timeout) 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project connectLocal(fd, address.getName(), address.getNamespace().getId()); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Binds this socket to an endpoint name. May only be called on an instance 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that has not yet been bound. 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param endpoint endpoint address 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void bind(LocalSocketAddress endpoint) throws IOException 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bindLocal(fd, endpoint.getName(), endpoint.getNamespace().getId()); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void listen(int backlog) throws IOException 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3164fa438ef72d125b4c0e7eb37a6667ca51ed325e4Neil Fuller try { 3174fa438ef72d125b4c0e7eb37a6667ca51ed325e4Neil Fuller Os.listen(fd, backlog); 3184fa438ef72d125b4c0e7eb37a6667ca51ed325e4Neil Fuller } catch (ErrnoException e) { 3194fa438ef72d125b4c0e7eb37a6667ca51ed325e4Neil Fuller throw e.rethrowAsIOException(); 3204fa438ef72d125b4c0e7eb37a6667ca51ed325e4Neil Fuller } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Accepts a new connection to the socket. Blocks until a new 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * connection arrives. 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param s a socket that will be used to represent the new connection. 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 330c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller protected void accept(LocalSocketImpl s) throws IOException { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 335c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller try { 336c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller s.fd = Os.accept(fd, null /* address */); 337c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller s.mFdCreatedInternally = true; 338c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller } catch (ErrnoException e) { 339c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller throw e.rethrowAsIOException(); 340c1eaeb93379fc8940f595cf21844fa24b8cd1734Neil Fuller } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves the input stream for this instance. 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return input stream 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException if socket has been closed or cannot be created. 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected InputStream getInputStream() throws IOException 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fis == null) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fis = new SocketInputStream(); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fis; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves the output stream for this instance. 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return output stream 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException if socket has been closed or cannot be created. 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected OutputStream getOutputStream() throws IOException 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fos == null) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fos = new SocketOutputStream(); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fos; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of bytes available for reading without blocking. 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return >= 0 count bytes available 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int available() throws IOException 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getInputStream().available(); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shuts down the input side of the socket. 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void shutdownInput() throws IOException 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 407a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller try { 408a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller Os.shutdown(fd, OsConstants.SHUT_RD); 409a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller } catch (ErrnoException e) { 410a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller throw e.rethrowAsIOException(); 411a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shuts down the output side of the socket. 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void shutdownOutput() throws IOException 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 425a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller try { 426a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller Os.shutdown(fd, OsConstants.SHUT_WR); 427a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller } catch (ErrnoException e) { 428a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller throw e.rethrowAsIOException(); 429a7f7c248c719a5e9b7dbe629e016ef73f89ce0e7Neil Fuller } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected FileDescriptor getFileDescriptor() 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fd; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean supportsUrgentData() 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void sendUrgentData(int data) throws IOException 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException ("not impled"); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Object getOption(int optID) throws IOException 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd == null) { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("socket not created"); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 453c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller try { 454c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller Object toReturn; 455c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller switch (optID) { 456c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_TIMEOUT: 457c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller StructTimeval timeval = Os.getsockoptTimeval(fd, OsConstants.SOL_SOCKET, 458c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller OsConstants.SO_SNDTIMEO); 459c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller toReturn = (int) timeval.toMillis(); 460c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 461c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_RCVBUF: 462c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_SNDBUF: 463c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_REUSEADDR: 464c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller int osOpt = javaSoToOsOpt(optID); 465c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller toReturn = Os.getsockoptInt(fd, OsConstants.SOL_SOCKET, osOpt); 466c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 467c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_LINGER: 468c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller StructLinger linger= 469c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller Os.getsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER); 470c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller if (!linger.isOn()) { 471c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller toReturn = -1; 472c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } else { 473c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller toReturn = linger.l_linger; 474c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 475c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 476c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.TCP_NODELAY: 477c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller toReturn = Os.getsockoptInt(fd, OsConstants.IPPROTO_TCP, 478c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller OsConstants.TCP_NODELAY); 479c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 480c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller default: 481c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller throw new IOException("Unknown option: " + optID); 482c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 483c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller return toReturn; 484c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } catch (ErrnoException e) { 485c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller throw e.rethrowAsIOException(); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOption(int optID, Object value) 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 491c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller 492c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller if (fd == null) { 493c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller throw new IOException("socket not created"); 494c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 495c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Boolean.FALSE is used to disable some options, so it 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is important to distinguish between FALSE and unset. 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * We define it here that -1 is unset, 0 is FALSE, and 1 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is TRUE. 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int boolValue = -1; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int intValue = 0; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value instanceof Integer) { 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intValue = (Integer)value; 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (value instanceof Boolean) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolValue = ((Boolean) value)? 1 : 0; 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IOException("bad value: " + value); 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 512c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller try { 513c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller switch (optID) { 514c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_LINGER: 515c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller StructLinger linger = new StructLinger(boolValue, intValue); 516c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller Os.setsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER, linger); 517c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 518c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_TIMEOUT: 519c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller /* 520c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller * SO_TIMEOUT from the core library gets converted to 521c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller * SO_SNDTIMEO, but the option is supposed to set both 522c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller * send and receive timeouts. Note: The incoming timeout 523c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller * value is in milliseconds. 524c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller */ 525c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller StructTimeval timeval = StructTimeval.fromMillis(intValue); 526c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_SNDTIMEO, 527c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller timeval); 528c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 529c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_RCVBUF: 530c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_SNDBUF: 531c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_REUSEADDR: 532c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller int osOpt = javaSoToOsOpt(optID); 533c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller Os.setsockoptInt(fd, OsConstants.SOL_SOCKET, osOpt, intValue); 534c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 535c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.TCP_NODELAY: 536c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller Os.setsockoptInt(fd, OsConstants.IPPROTO_TCP, OsConstants.TCP_NODELAY, 537c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller intValue); 538c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller break; 539c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller default: 540c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller throw new IOException("Unknown option: " + optID); 541c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 542c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } catch (ErrnoException e) { 543c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller throw e.rethrowAsIOException(); 544c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enqueues a set of file descriptors to send to the peer. The queue 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is one deep. The file descriptors will be sent with the next write 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of normal data, and will be delivered in a single ancillary message. 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine. 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fds non-null; file descriptors to send. 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFileDescriptorsForSend(FileDescriptor[] fds) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(writeMonitor) { 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project outboundFileDescriptors = fds; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves a set of file descriptors that a peer has sent through 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an ancillary message. This method retrieves the most recent set sent, 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and then returns null until a new set arrives. 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * File descriptors may only be passed along with regular data, so this 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * method can only return a non-null after a read operation. 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return null or file descriptor array 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FileDescriptor[] getAncillaryFileDescriptors() throws IOException { 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(readMonitor) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileDescriptor[] result = inboundFileDescriptors; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inboundFileDescriptors = null; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves the credentials of this socket's peer. Only valid on 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * connected sockets. 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return non-null; peer credentials 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 588c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller public Credentials getPeerCredentials() throws IOException { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getPeerCredentials_native(fd); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieves the socket name from the OS. 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return non-null; socket name 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException on failure 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 598c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller public LocalSocketAddress getSockAddress() throws IOException { 599c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller // This method has never been implemented. 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws IOException { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 607c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller 608c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller private static int javaSoToOsOpt(int optID) { 609c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller switch (optID) { 610c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_SNDBUF: 611c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller return OsConstants.SO_SNDBUF; 612c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_RCVBUF: 613c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller return OsConstants.SO_RCVBUF; 614c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller case SocketOptions.SO_REUSEADDR: 615c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller return OsConstants.SO_REUSEADDR; 616c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller default: 617c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller throw new UnsupportedOperationException("Unknown option: " + optID); 618c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 619c80af6d84d8fb729f17028ac533fac07bb7c4c5dNeil Fuller } 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 621