1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18ae704b984c10a63883cc366e823d53902d6ac7a9Elliott Hughespackage java.nio; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileDescriptor; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 228de7cf6bff36093dda9e25a1ab3718720cb54906Elliott Hughesimport java.net.PlainServerSocketImpl; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.ServerSocket; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketAddress; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketImpl; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketTimeoutException; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.ClosedChannelException; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.IllegalBlockingModeException; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.NotYetBoundException; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.ServerSocketChannel; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SocketChannel; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.spi.SelectorProvider; 34a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughesimport libcore.io.IoUtils; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 366b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson/** 376b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson * The default ServerSocketChannel. 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 39d320e321d5567a4ac94b6e5874eda4b1f1189e13Elliott Hughesfinal class ServerSocketChannelImpl extends ServerSocketChannel implements FileDescriptorChannel { 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes private final ServerSocketAdapter socket; 42a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes private final SocketImpl impl; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 446b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson private boolean isBound = false; 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 465e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes private final Object acceptLock = new Object(); 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public ServerSocketChannelImpl(SelectorProvider sp) throws IOException { 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(sp); 50a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes this.socket = new ServerSocketAdapter(this); 51a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes this.impl = socket.getImpl$(); 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 546b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public ServerSocket socket() { 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return socket; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 588cc54e9f098c4f299d2b88bb2b9110ce44354ed7Elliott Hughes @Override public SocketChannel accept() throws IOException { 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isOpen()) { 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ClosedChannelException(); 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isBound) { 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new NotYetBoundException(); 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 666b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson // Create an empty socket channel. This will be populated by ServerSocketAdapter.accept. 67a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes SocketChannelImpl result = new SocketChannelImpl(provider(), false); 68a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes boolean connected = false; 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project begin(); 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (acceptLock) { 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (blockingLock()) { 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project do { 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 75a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes socket.implAccept(result); 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // select successfully, break out immediately. 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (SocketTimeoutException e) { 796b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson // continue to accept if the channel is in blocking mode. 80a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes // TODO: does this make sense? why does blocking imply no timeouts? 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 82a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes } while (isBlocking()); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 86a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes end(result.socket().isConnected()); 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 88a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes return result.socket().isConnected() ? result : null; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 91a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes @Override protected void implConfigureBlocking(boolean blocking) throws IOException { 92a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes synchronized (blockingLock()) { 93a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes IoUtils.setBlocking(impl.getFD$(), blocking); 94a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes } 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized protected void implCloseSelectableChannel() throws IOException { 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!socket.isClosed()) { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project socket.close(); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public FileDescriptor getFD() { 104a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes return impl.getFD$(); 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1076b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson private static class ServerSocketAdapter extends ServerSocket { 1086b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson private final ServerSocketChannelImpl channelImpl; 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 110a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes ServerSocketAdapter(ServerSocketChannelImpl aChannelImpl) throws IOException { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.channelImpl = aChannelImpl; 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1146b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public void bind(SocketAddress localAddress, int backlog) throws IOException { 1156b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson super.bind(localAddress, backlog); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project channelImpl.isBound = true; 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1196b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public Socket accept() throws IOException { 1206b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson if (!channelImpl.isBound) { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalBlockingModeException(); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SocketChannel sc = channelImpl.accept(); 124b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes if (sc == null) { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalBlockingModeException(); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sc.socket(); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 130a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes public Socket implAccept(SocketChannelImpl clientSocketChannel) throws IOException { 131a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes Socket clientSocket = clientSocketChannel.socket(); 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean connectOK = false; 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 135a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes super.implAccept(clientSocket); 136a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes clientSocketChannel.setConnected(); 137a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes clientSocketChannel.setBound(true); 138a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes clientSocketChannel.finishAccept(); 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project connectOK = true; 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!connectOK) { 143a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes clientSocket.close(); 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 146a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes return clientSocket; 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1496b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public ServerSocketChannel getChannel() { 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return channelImpl; 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1536b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public boolean isBound() { 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return channelImpl.isBound; 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1576b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public void bind(SocketAddress localAddress) throws IOException { 1586b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson super.bind(localAddress); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project channelImpl.isBound = true; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1626b739231f8985f33f20672fe727fde0d0f023eadJesse Wilson @Override public void close() throws IOException { 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (channelImpl) { 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (channelImpl.isOpen()) { 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project channelImpl.close(); 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.close(); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 173