Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java
38918 views
/*1* Copyright (c) 2000, 2021, 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.isOpen()) {201throw new ClosedChannelException();202}203if (!sc.isBlocking())204throw new IllegalBlockingModeException();205206if (timeout == 0)207return sc.read(bb);208209sc.configureBlocking(false);210try {211int n;212if ((n = sc.read(bb)) != 0)213return n;214long to = timeout;215for (;;) {216if (!sc.isOpen())217throw new ClosedChannelException();218long st = System.currentTimeMillis();219int result = sc.poll(Net.POLLIN, to);220if (result > 0) {221if ((n = sc.read(bb)) != 0)222return n;223}224to -= System.currentTimeMillis() - st;225if (to <= 0)226throw new SocketTimeoutException();227}228} finally {229try {230sc.configureBlocking(true);231} catch (ClosedChannelException e) { }232}233}234}235}236237private InputStream socketInputStream = null;238239public InputStream getInputStream() throws IOException {240if (!sc.isOpen())241throw new SocketException("Socket is closed");242if (!sc.isConnected())243throw new SocketException("Socket is not connected");244if (!sc.isInputOpen())245throw new SocketException("Socket input is shutdown");246if (socketInputStream == null) {247try {248socketInputStream = AccessController.doPrivileged(249new PrivilegedExceptionAction<InputStream>() {250public InputStream run() throws IOException {251return new SocketInputStream();252}253});254} catch (java.security.PrivilegedActionException e) {255throw (IOException)e.getException();256}257}258return socketInputStream;259}260261public OutputStream getOutputStream() throws IOException {262if (!sc.isOpen())263throw new SocketException("Socket is closed");264if (!sc.isConnected())265throw new SocketException("Socket is not connected");266if (!sc.isOutputOpen())267throw new SocketException("Socket output is shutdown");268OutputStream os = null;269try {270os = AccessController.doPrivileged(271new PrivilegedExceptionAction<OutputStream>() {272public OutputStream run() throws IOException {273return Channels.newOutputStream(sc);274}275});276} catch (java.security.PrivilegedActionException e) {277throw (IOException)e.getException();278}279return os;280}281282private void setBooleanOption(SocketOption<Boolean> name, boolean value)283throws SocketException284{285try {286sc.setOption(name, value);287} catch (IOException x) {288Net.translateToSocketException(x);289}290}291292private void setIntOption(SocketOption<Integer> name, int value)293throws SocketException294{295try {296sc.setOption(name, value);297} catch (IOException x) {298Net.translateToSocketException(x);299}300}301302private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException {303try {304return sc.getOption(name).booleanValue();305} catch (IOException x) {306Net.translateToSocketException(x);307return false; // keep compiler happy308}309}310311private int getIntOption(SocketOption<Integer> name) throws SocketException {312try {313return sc.getOption(name).intValue();314} catch (IOException x) {315Net.translateToSocketException(x);316return -1; // keep compiler happy317}318}319320public void setTcpNoDelay(boolean on) throws SocketException {321setBooleanOption(StandardSocketOptions.TCP_NODELAY, on);322}323324public boolean getTcpNoDelay() throws SocketException {325return getBooleanOption(StandardSocketOptions.TCP_NODELAY);326}327328public void setSoLinger(boolean on, int linger) throws SocketException {329if (!on)330linger = -1;331setIntOption(StandardSocketOptions.SO_LINGER, linger);332}333334public int getSoLinger() throws SocketException {335return getIntOption(StandardSocketOptions.SO_LINGER);336}337338public void sendUrgentData(int data) throws IOException {339int n = sc.sendOutOfBandData((byte) data);340if (n == 0)341throw new IOException("Socket buffer full");342}343344public void setOOBInline(boolean on) throws SocketException {345setBooleanOption(ExtendedSocketOption.SO_OOBINLINE, on);346}347348public boolean getOOBInline() throws SocketException {349return getBooleanOption(ExtendedSocketOption.SO_OOBINLINE);350}351352public void setSoTimeout(int timeout) throws SocketException {353if (timeout < 0)354throw new IllegalArgumentException("timeout can't be negative");355this.timeout = timeout;356}357358public int getSoTimeout() throws SocketException {359return timeout;360}361362public void setSendBufferSize(int size) throws SocketException {363// size 0 valid for SocketChannel, invalid for Socket364if (size <= 0)365throw new IllegalArgumentException("Invalid send size");366setIntOption(StandardSocketOptions.SO_SNDBUF, size);367}368369public int getSendBufferSize() throws SocketException {370return getIntOption(StandardSocketOptions.SO_SNDBUF);371}372373public void setReceiveBufferSize(int size) throws SocketException {374// size 0 valid for SocketChannel, invalid for Socket375if (size <= 0)376throw new IllegalArgumentException("Invalid receive size");377setIntOption(StandardSocketOptions.SO_RCVBUF, size);378}379380public int getReceiveBufferSize() throws SocketException {381return getIntOption(StandardSocketOptions.SO_RCVBUF);382}383384public void setKeepAlive(boolean on) throws SocketException {385setBooleanOption(StandardSocketOptions.SO_KEEPALIVE, on);386}387388public boolean getKeepAlive() throws SocketException {389return getBooleanOption(StandardSocketOptions.SO_KEEPALIVE);390}391392public void setTrafficClass(int tc) throws SocketException {393setIntOption(StandardSocketOptions.IP_TOS, tc);394}395396public int getTrafficClass() throws SocketException {397return getIntOption(StandardSocketOptions.IP_TOS);398}399400public void setReuseAddress(boolean on) throws SocketException {401setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);402}403404public boolean getReuseAddress() throws SocketException {405return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);406}407408public void close() throws IOException {409sc.close();410}411412public void shutdownInput() throws IOException {413try {414sc.shutdownInput();415} catch (Exception x) {416Net.translateException(x);417}418}419420public void shutdownOutput() throws IOException {421try {422sc.shutdownOutput();423} catch (Exception x) {424Net.translateException(x);425}426}427428public String toString() {429if (sc.isConnected())430return "Socket[addr=" + getInetAddress() +431",port=" + getPort() +432",localport=" + getLocalPort() + "]";433return "Socket[unconnected]";434}435436public boolean isConnected() {437return sc.isConnected();438}439440public boolean isBound() {441return sc.localAddress() != null;442}443444public boolean isClosed() {445return !sc.isOpen();446}447448public boolean isInputShutdown() {449return !sc.isInputOpen();450}451452public boolean isOutputShutdown() {453return !sc.isOutputOpen();454}455456}457458459