Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java
83408 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.io.IOException;28import java.io.InputStream;29import java.io.OutputStream;30import java.net.InetAddress;31import java.net.InetSocketAddress;32import java.net.Socket;33import java.net.SocketAddress;34import java.net.SocketException;35import java.net.SocketImpl;36import java.net.SocketOption;37import java.net.SocketTimeoutException;38import java.net.StandardSocketOptions;39import java.nio.ByteBuffer;40import java.nio.channels.Channels;41import java.nio.channels.ClosedChannelException;42import java.nio.channels.IllegalBlockingModeException;43import java.nio.channels.SocketChannel;44import java.security.AccessController;45import java.security.PrivilegedExceptionAction;46import java.util.*;474849// Make a socket channel look like a socket.50//51// The only aspects of java.net.Socket-hood that we don't attempt to emulate52// here are the interrupted-I/O exceptions (which our Solaris implementations53// attempt to support) and the sending of urgent data. Otherwise an adapted54// socket should look enough like a real java.net.Socket to fool most of the55// developers most of the time, right down to the exception message strings.56//57// The methods in this class are defined in exactly the same order as in58// java.net.Socket so as to simplify tracking future changes to that class.59//6061class SocketAdaptor62extends Socket63{6465// The channel being adapted66private final SocketChannelImpl sc;6768// Timeout "option" value for reads69private volatile int timeout = 0;7071private SocketAdaptor(SocketChannelImpl sc) throws SocketException {72super((SocketImpl) null);73this.sc = sc;74}7576public static Socket create(SocketChannelImpl sc) {77try {78return new SocketAdaptor(sc);79} catch (SocketException e) {80throw new InternalError("Should not reach here");81}82}8384public SocketChannel getChannel() {85return sc;86}8788// Override this method just to protect against changes in the superclass89//90public void connect(SocketAddress remote) throws IOException {91connect(remote, 0);92}9394public void connect(SocketAddress remote, int timeout) throws IOException {95if (remote == null)96throw new IllegalArgumentException("connect: The address can't be null");97if (timeout < 0)98throw new IllegalArgumentException("connect: timeout can't be negative");99100synchronized (sc.blockingLock()) {101if (!sc.isBlocking())102throw new IllegalBlockingModeException();103104try {105if (timeout == 0) {106sc.connect(remote);107return;108}109110sc.configureBlocking(false);111try {112if (sc.connect(remote))113return;114long to = timeout;115for (;;) {116if (!sc.isOpen())117throw new ClosedChannelException();118long st = System.currentTimeMillis();119120int result = sc.poll(Net.POLLCONN, to);121if (result > 0 && sc.finishConnect())122break;123to -= System.currentTimeMillis() - st;124if (to <= 0) {125try {126sc.close();127} catch (IOException x) { }128throw new SocketTimeoutException();129}130}131} finally {132try {133sc.configureBlocking(true);134} catch (ClosedChannelException e) { }135}136137} catch (Exception x) {138Net.translateException(x, true);139}140}141142}143144public void bind(SocketAddress local) throws IOException {145try {146sc.bind(local);147} catch (Exception x) {148Net.translateException(x);149}150}151152public InetAddress getInetAddress() {153SocketAddress remote = sc.remoteAddress();154if (remote == null) {155return null;156} else {157return ((InetSocketAddress)remote).getAddress();158}159}160161public InetAddress getLocalAddress() {162if (sc.isOpen()) {163InetSocketAddress local = sc.localAddress();164if (local != null) {165return Net.getRevealedLocalAddress(local).getAddress();166}167}168return new InetSocketAddress(0).getAddress();169}170171public int getPort() {172SocketAddress remote = sc.remoteAddress();173if (remote == null) {174return 0;175} else {176return ((InetSocketAddress)remote).getPort();177}178}179180public int getLocalPort() {181SocketAddress local = sc.localAddress();182if (local == null) {183return -1;184} else {185return ((InetSocketAddress)local).getPort();186}187}188189private class SocketInputStream190extends ChannelInputStream191{192private SocketInputStream() {193super(sc);194}195196protected int read(ByteBuffer bb)197throws IOException198{199synchronized (sc.blockingLock()) {200if (!sc.isBlocking())201throw new IllegalBlockingModeException();202203if (timeout == 0)204return sc.read(bb);205206sc.configureBlocking(false);207try {208int n;209if ((n = sc.read(bb)) != 0)210return n;211long to = timeout;212for (;;) {213if (!sc.isOpen())214throw new ClosedChannelException();215long st = System.currentTimeMillis();216int result = sc.poll(Net.POLLIN, to);217if (result > 0) {218if ((n = sc.read(bb)) != 0)219return n;220}221to -= System.currentTimeMillis() - st;222if (to <= 0)223throw new SocketTimeoutException();224}225} finally {226try {227sc.configureBlocking(true);228} catch (ClosedChannelException e) { }229}230}231}232}233234private InputStream socketInputStream = null;235236public InputStream getInputStream() throws IOException {237if (!sc.isOpen())238throw new SocketException("Socket is closed");239if (!sc.isConnected())240throw new SocketException("Socket is not connected");241if (!sc.isInputOpen())242throw new SocketException("Socket input is shutdown");243if (socketInputStream == null) {244try {245socketInputStream = AccessController.doPrivileged(246new PrivilegedExceptionAction<InputStream>() {247public InputStream run() throws IOException {248return new SocketInputStream();249}250});251} catch (java.security.PrivilegedActionException e) {252throw (IOException)e.getException();253}254}255return socketInputStream;256}257258public OutputStream getOutputStream() throws IOException {259if (!sc.isOpen())260throw new SocketException("Socket is closed");261if (!sc.isConnected())262throw new SocketException("Socket is not connected");263if (!sc.isOutputOpen())264throw new SocketException("Socket output is shutdown");265OutputStream os = null;266try {267os = AccessController.doPrivileged(268new PrivilegedExceptionAction<OutputStream>() {269public OutputStream run() throws IOException {270return Channels.newOutputStream(sc);271}272});273} catch (java.security.PrivilegedActionException e) {274throw (IOException)e.getException();275}276return os;277}278279private void setBooleanOption(SocketOption<Boolean> name, boolean value)280throws SocketException281{282try {283sc.setOption(name, value);284} catch (IOException x) {285Net.translateToSocketException(x);286}287}288289private void setIntOption(SocketOption<Integer> name, int value)290throws SocketException291{292try {293sc.setOption(name, value);294} catch (IOException x) {295Net.translateToSocketException(x);296}297}298299private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException {300try {301return sc.getOption(name).booleanValue();302} catch (IOException x) {303Net.translateToSocketException(x);304return false; // keep compiler happy305}306}307308private int getIntOption(SocketOption<Integer> name) throws SocketException {309try {310return sc.getOption(name).intValue();311} catch (IOException x) {312Net.translateToSocketException(x);313return -1; // keep compiler happy314}315}316317public void setTcpNoDelay(boolean on) throws SocketException {318setBooleanOption(StandardSocketOptions.TCP_NODELAY, on);319}320321public boolean getTcpNoDelay() throws SocketException {322return getBooleanOption(StandardSocketOptions.TCP_NODELAY);323}324325public void setSoLinger(boolean on, int linger) throws SocketException {326if (!on)327linger = -1;328setIntOption(StandardSocketOptions.SO_LINGER, linger);329}330331public int getSoLinger() throws SocketException {332return getIntOption(StandardSocketOptions.SO_LINGER);333}334335public void sendUrgentData(int data) throws IOException {336int n = sc.sendOutOfBandData((byte) data);337if (n == 0)338throw new IOException("Socket buffer full");339}340341public void setOOBInline(boolean on) throws SocketException {342setBooleanOption(ExtendedSocketOption.SO_OOBINLINE, on);343}344345public boolean getOOBInline() throws SocketException {346return getBooleanOption(ExtendedSocketOption.SO_OOBINLINE);347}348349public void setSoTimeout(int timeout) throws SocketException {350if (timeout < 0)351throw new IllegalArgumentException("timeout can't be negative");352this.timeout = timeout;353}354355public int getSoTimeout() throws SocketException {356return timeout;357}358359public void setSendBufferSize(int size) throws SocketException {360// size 0 valid for SocketChannel, invalid for Socket361if (size <= 0)362throw new IllegalArgumentException("Invalid send size");363setIntOption(StandardSocketOptions.SO_SNDBUF, size);364}365366public int getSendBufferSize() throws SocketException {367return getIntOption(StandardSocketOptions.SO_SNDBUF);368}369370public void setReceiveBufferSize(int size) throws SocketException {371// size 0 valid for SocketChannel, invalid for Socket372if (size <= 0)373throw new IllegalArgumentException("Invalid receive size");374setIntOption(StandardSocketOptions.SO_RCVBUF, size);375}376377public int getReceiveBufferSize() throws SocketException {378return getIntOption(StandardSocketOptions.SO_RCVBUF);379}380381public void setKeepAlive(boolean on) throws SocketException {382setBooleanOption(StandardSocketOptions.SO_KEEPALIVE, on);383}384385public boolean getKeepAlive() throws SocketException {386return getBooleanOption(StandardSocketOptions.SO_KEEPALIVE);387}388389public void setTrafficClass(int tc) throws SocketException {390setIntOption(StandardSocketOptions.IP_TOS, tc);391}392393public int getTrafficClass() throws SocketException {394return getIntOption(StandardSocketOptions.IP_TOS);395}396397public void setReuseAddress(boolean on) throws SocketException {398setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);399}400401public boolean getReuseAddress() throws SocketException {402return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);403}404405public void close() throws IOException {406sc.close();407}408409public void shutdownInput() throws IOException {410try {411sc.shutdownInput();412} catch (Exception x) {413Net.translateException(x);414}415}416417public void shutdownOutput() throws IOException {418try {419sc.shutdownOutput();420} catch (Exception x) {421Net.translateException(x);422}423}424425public String toString() {426if (sc.isConnected())427return "Socket[addr=" + getInetAddress() +428",port=" + getPort() +429",localport=" + getLocalPort() + "]";430return "Socket[unconnected]";431}432433public boolean isConnected() {434return sc.isConnected();435}436437public boolean isBound() {438return sc.localAddress() != null;439}440441public boolean isClosed() {442return !sc.isOpen();443}444445public boolean isInputShutdown() {446return !sc.isInputOpen();447}448449public boolean isOutputShutdown() {450return !sc.isOutputOpen();451}452453}454455456