< prev index next >

src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java

Print this page




  54     /* instance variable for SO_TIMEOUT */
  55     int timeout;   // timeout in millisec
  56     // traffic class
  57     private int trafficClass;
  58 
  59     private boolean shut_rd = false;
  60     private boolean shut_wr = false;
  61 
  62     private SocketInputStream socketInputStream = null;
  63     private SocketOutputStream socketOutputStream = null;
  64 
  65     /* number of threads using the FileDescriptor */
  66     protected int fdUseCount = 0;
  67 
  68     /* lock when increment/decrementing fdUseCount */
  69     protected final Object fdLock = new Object();
  70 
  71     /* indicates a close is pending on the file descriptor */
  72     protected boolean closePending = false;
  73 






  74     /* indicates connection reset state */
  75     private volatile boolean connectionReset;
  76 
  77    /* whether this Socket is a stream (TCP) socket or not (UDP)
  78     */
  79     protected boolean stream;
  80 
  81     /**
  82      * Load net library into runtime.
  83      */
  84     static {
  85         java.security.AccessController.doPrivileged(
  86             new java.security.PrivilegedAction<>() {
  87                 public Void run() {
  88                     System.loadLibrary("net");
  89                     return null;
  90                 }
  91             });
  92     }
  93 
  94     private static volatile boolean checkedReusePort;
  95     private static volatile boolean isReusePortAvailable;
  96 
  97     /**
  98      * Tells whether SO_REUSEPORT is supported.
  99      */
 100     static boolean isReusePortAvailable() {
 101         if (!checkedReusePort) {
 102             isReusePortAvailable = isReusePortAvailable0();
 103             checkedReusePort = true;
 104         }
 105         return isReusePortAvailable;
 106     }
 107 




 108     /**
 109      * Returns a set of SocketOptions supported by this impl and by this impl's
 110      * socket (Socket or ServerSocket)
 111      *
 112      * @return a Set of SocketOptions
 113      */
 114     @Override
 115     protected Set<SocketOption<?>> supportedOptions() {
 116         Set<SocketOption<?>> options;
 117         if (isReusePortAvailable()) {
 118             options = new HashSet<>();
 119             options.addAll(super.supportedOptions());
 120             options.add(StandardSocketOptions.SO_REUSEPORT);
 121             options = Collections.unmodifiableSet(options);
 122         } else {
 123             options = super.supportedOptions();
 124         }
 125         return options;
 126     }
 127 
 128     /**
 129      * Creates a socket with a boolean that specifies whether this
 130      * is a stream socket (true) or an unconnected UDP socket (false).
 131      */
 132     protected synchronized void create(boolean stream) throws IOException {
 133         this.stream = stream;
 134         if (!stream) {
 135             ResourceManager.beforeUdpCreate();
 136             // only create the fd after we know we will be able to create the socket
 137             fd = new FileDescriptor();
 138             try {
 139                 socketCreate(false);
 140                 SocketCleanable.register(fd);
 141             } catch (IOException ioe) {
 142                 ResourceManager.afterUdpClose();
 143                 fd = null;
 144                 throw ioe;
 145             }
 146         } else {
 147             fd = new FileDescriptor();
 148             socketCreate(true);
 149             SocketCleanable.register(fd);
 150         }
 151         if (socket != null)
 152             socket.setCreated();
 153         if (serverSocket != null)
 154             serverSocket.setCreated();
 155     }
 156 
 157     /**
 158      * Creates a socket and connects it to the specified port on
 159      * the specified host.
 160      * @param host the specified host
 161      * @param port the specified port
 162      */
 163     protected void connect(String host, int port)
 164         throws UnknownHostException, IOException
 165     {
 166         boolean connected = false;
 167         try {
 168             InetAddress address = InetAddress.getByName(host);
 169             this.port = port;
 170             this.address = address;
 171 
 172             connectToAddress(address, port, timeout);
 173             connected = true;
 174         } finally {


 228             connectToAddress(this.address, port, timeout);
 229             connected = true;
 230         } finally {
 231             if (!connected) {
 232                 try {
 233                     close();
 234                 } catch (IOException ioe) {
 235                     /* Do nothing. If connect threw an exception then
 236                        it will be passed up the call stack */
 237                 }
 238             }
 239         }
 240     }
 241 
 242     private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
 243         if (address.isAnyLocalAddress()) {
 244             doConnect(InetAddress.getLocalHost(), port, timeout);
 245         } else {
 246             doConnect(address, port, timeout);
 247         }


 248     }
 249 
 250     public void setOption(int opt, Object val) throws SocketException {
 251         if (isClosedOrPending()) {
 252             throw new SocketException("Socket Closed");
 253         }
 254         boolean on = true;
 255         switch (opt) {
 256             /* check type safety b4 going native.  These should never
 257              * fail, since only java.Socket* has access to
 258              * PlainSocketImpl.setOption().
 259              */
 260         case SO_LINGER:
 261             if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
 262                 throw new SocketException("Bad parameter for option");
 263             if (val instanceof Boolean) {
 264                 /* true only if disabling - enabling should be Integer */
 265                 on = false;
 266             }
 267             break;


 344         case SO_OOBINLINE:
 345             ret = socketGetOption(opt, null);
 346             return Boolean.valueOf(ret != -1);
 347         case SO_LINGER:
 348             ret = socketGetOption(opt, null);
 349             return (ret == -1) ? Boolean.FALSE: (Object)(ret);
 350         case SO_REUSEADDR:
 351             ret = socketGetOption(opt, null);
 352             return Boolean.valueOf(ret != -1);
 353         case SO_BINDADDR:
 354             InetAddressContainer in = new InetAddressContainer();
 355             ret = socketGetOption(opt, in);
 356             return in.addr;
 357         case SO_SNDBUF:
 358         case SO_RCVBUF:
 359             ret = socketGetOption(opt, null);
 360             return ret;
 361         case IP_TOS:
 362             try {
 363                 ret = socketGetOption(opt, null);

 364                 if (ret == -1) { // ipv6 tos
 365                     return trafficClass;
 366                 } else {
 367                     return ret;
 368                 }
 369             } catch (SocketException se) {
 370                     // TODO - should make better effort to read TOS or TCLASS

 371                     return trafficClass; // ipv6 tos
 372             }
 373         case SO_KEEPALIVE:
 374             ret = socketGetOption(opt, null);
 375             return Boolean.valueOf(ret != -1);
 376         case SO_REUSEPORT:
 377             if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
 378                 throw new UnsupportedOperationException("unsupported option");
 379             }
 380             ret = socketGetOption(opt, null);
 381             return Boolean.valueOf(ret != -1);
 382         // should never get here
 383         default:
 384             return null;
 385         }
 386     }
 387 
 388     /**
 389      * The workhorse of the connection operation.  Tries several times to
 390      * establish a connection to the given <host, port>.  If unsuccessful,
 391      * throws an IOException indicating what went wrong.
 392      */
 393 
 394     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
 395         synchronized (fdLock) {
 396             if (!closePending && (socket == null || !socket.isBound())) {
 397                 NetHooks.beforeTcpConnect(fd, address, port);
 398             }
 399         }
 400         try {
 401             acquireFD();
 402             try {
 403                 socketConnect(address, port, timeout);
 404                 /* socket may have been closed during poll/select */
 405                 synchronized (fdLock) {
 406                     if (closePending) {
 407                         throw new SocketException ("Socket closed");
 408                     }
 409                 }
 410                 // If we have a ref. to the Socket, then sets the flags
 411                 // created, bound & connected to true.
 412                 // This is normally done in Socket.connect() but some
 413                 // subclasses of Socket may call impl.connect() directly!
 414                 if (socket != null) {
 415                     socket.setBound();
 416                     socket.setConnected();
 417                 }
 418             } finally {
 419                 releaseFD();
 420             }
 421         } catch (IOException e) {
 422             close();
 423             throw SocketExceptions.of(e, new InetSocketAddress(address, port));
 424         }
 425     }
 426 
 427     /**
 428      * Binds the socket to the specified address of the specified local port.
 429      * @param address the address
 430      * @param lport the port
 431      */
 432     protected synchronized void bind(InetAddress address, int lport)
 433         throws IOException
 434     {
 435        synchronized (fdLock) {
 436             if (!closePending && (socket == null || !socket.isBound())) {
 437                 NetHooks.beforeTcpBind(fd, address, lport);
 438             }
 439         }
 440         socketBind(address, lport);
 441         if (socket != null)
 442             socket.setBound();
 443         if (serverSocket != null)
 444             serverSocket.setBound();
 445     }
 446 
 447     /**
 448      * Listens, for a specified amount of time, for connections.
 449      * @param count the amount of time to listen for connections
 450      */
 451     protected synchronized void listen(int count) throws IOException {
 452         socketListen(count);
 453     }
 454 
 455     /**
 456      * Accepts connections.
 457      * @param si the socket impl
 458      */
 459     protected void accept(SocketImpl si) throws IOException {
 460         si.fd = new FileDescriptor();
 461         acquireFD();
 462         try {
 463             socketAccept(si);



 464         } finally {
 465             releaseFD();
 466         }
 467         SocketCleanable.register(si.fd);
 468     }
 469 
 470     /**
 471      * Gets an InputStream for this socket.
 472      */
 473     protected synchronized InputStream getInputStream() throws IOException {
 474         synchronized (fdLock) {
 475             if (isClosedOrPending())
 476                 throw new IOException("Socket Closed");
 477             if (shut_rd)
 478                 throw new IOException("Socket input is shutdown");
 479             if (socketInputStream == null) {
 480                 PrivilegedExceptionAction<SocketInputStream> pa = () -> new SocketInputStream(this);
 481                 try {
 482                     socketInputStream = AccessController.doPrivileged(pa);
 483                 } catch (PrivilegedActionException e) {


 710     public int getTimeout() {
 711         return timeout;
 712     }
 713 
 714     /*
 715      * "Pre-close" a socket by dup'ing the file descriptor - this enables
 716      * the socket to be closed without releasing the file descriptor.
 717      */
 718     private void socketPreClose() throws IOException {
 719         socketClose0(true);
 720     }
 721 
 722     /*
 723      * Close the socket (and release the file descriptor).
 724      */
 725     protected void socketClose() throws IOException {
 726         SocketCleanable.unregister(fd);
 727         socketClose0(false);
 728     }
 729 
 730     abstract void socketCreate(boolean isServer) throws IOException;
 731     abstract void socketConnect(InetAddress address, int port, int timeout)
 732         throws IOException;
 733     abstract void socketBind(InetAddress address, int port)
 734         throws IOException;
 735     abstract void socketListen(int count)
 736         throws IOException;
 737     abstract void socketAccept(SocketImpl s)
 738         throws IOException;
 739     abstract int socketAvailable()
 740         throws IOException;
 741     abstract void socketClose0(boolean useDeferredClose)
 742         throws IOException;
 743     abstract void socketShutdown(int howto)
 744         throws IOException;
 745     abstract void socketSetOption(int cmd, boolean on, Object value)
 746         throws SocketException;
 747     abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
 748     abstract void socketSendUrgentData(int data)
 749         throws IOException;
 750 


  54     /* instance variable for SO_TIMEOUT */
  55     int timeout;   // timeout in millisec
  56     // traffic class
  57     private int trafficClass;
  58 
  59     private boolean shut_rd = false;
  60     private boolean shut_wr = false;
  61 
  62     private SocketInputStream socketInputStream = null;
  63     private SocketOutputStream socketOutputStream = null;
  64 
  65     /* number of threads using the FileDescriptor */
  66     protected int fdUseCount = 0;
  67 
  68     /* lock when increment/decrementing fdUseCount */
  69     protected final Object fdLock = new Object();
  70 
  71     /* indicates a close is pending on the file descriptor */
  72     protected boolean closePending = false;
  73 
  74     /* true, if and only if, the socket is bound */
  75     volatile boolean bound;
  76 
  77     /* true, if and only if, the socket is connected */
  78     volatile boolean connected;
  79 
  80     /* indicates connection reset state */
  81     private volatile boolean connectionReset;
  82 
  83    /* whether this Socket is a stream (TCP) socket or not (UDP)
  84     */
  85     protected boolean stream;
  86 
  87     /**
  88      * Load net library into runtime.
  89      */
  90     static {
  91         java.security.AccessController.doPrivileged(
  92             new java.security.PrivilegedAction<>() {
  93                 public Void run() {
  94                     System.loadLibrary("net");
  95                     return null;
  96                 }
  97             });
  98     }
  99 
 100     private static volatile boolean checkedReusePort;
 101     private static volatile boolean isReusePortAvailable;
 102 
 103     /**
 104      * Tells whether SO_REUSEPORT is supported.
 105      */
 106     static boolean isReusePortAvailable() {
 107         if (!checkedReusePort) {
 108             isReusePortAvailable = isReusePortAvailable0();
 109             checkedReusePort = true;
 110         }
 111         return isReusePortAvailable;
 112     }
 113 
 114     AbstractPlainSocketImpl(boolean server) {
 115         super(server);
 116     }
 117 
 118     /**
 119      * Returns a set of SocketOptions supported by this impl and by this impl's
 120      * socket (Socket or ServerSocket)
 121      *
 122      * @return a Set of SocketOptions
 123      */
 124     @Override
 125     protected Set<SocketOption<?>> supportedOptions() {
 126         Set<SocketOption<?>> options;
 127         if (isReusePortAvailable()) {
 128             options = new HashSet<>();
 129             options.addAll(super.supportedOptions());
 130             options.add(StandardSocketOptions.SO_REUSEPORT);
 131             options = Collections.unmodifiableSet(options);
 132         } else {
 133             options = super.supportedOptions();
 134         }
 135         return options;
 136     }
 137 
 138     /**
 139      * Creates a socket with a boolean that specifies whether this
 140      * is a stream socket (true) or an unconnected UDP socket (false).
 141      */
 142     protected synchronized void create(boolean stream) throws IOException {
 143         this.stream = stream;
 144         if (!stream) {
 145             ResourceManager.beforeUdpCreate();
 146             // only create the fd after we know we will be able to create the socket
 147             fd = new FileDescriptor();
 148             try {
 149                 socketCreate(false, server);
 150                 SocketCleanable.register(fd);
 151             } catch (IOException ioe) {
 152                 ResourceManager.afterUdpClose();
 153                 fd = null;
 154                 throw ioe;
 155             }
 156         } else {
 157             fd = new FileDescriptor();
 158             socketCreate(true, server);
 159             SocketCleanable.register(fd);
 160         }




 161     }
 162 
 163     /**
 164      * Creates a socket and connects it to the specified port on
 165      * the specified host.
 166      * @param host the specified host
 167      * @param port the specified port
 168      */
 169     protected void connect(String host, int port)
 170         throws UnknownHostException, IOException
 171     {
 172         boolean connected = false;
 173         try {
 174             InetAddress address = InetAddress.getByName(host);
 175             this.port = port;
 176             this.address = address;
 177 
 178             connectToAddress(address, port, timeout);
 179             connected = true;
 180         } finally {


 234             connectToAddress(this.address, port, timeout);
 235             connected = true;
 236         } finally {
 237             if (!connected) {
 238                 try {
 239                     close();
 240                 } catch (IOException ioe) {
 241                     /* Do nothing. If connect threw an exception then
 242                        it will be passed up the call stack */
 243                 }
 244             }
 245         }
 246     }
 247 
 248     private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
 249         if (address.isAnyLocalAddress()) {
 250             doConnect(InetAddress.getLocalHost(), port, timeout);
 251         } else {
 252             doConnect(address, port, timeout);
 253         }
 254         connected = true;
 255         bound = true;  // implicitly bound
 256     }
 257 
 258     public void setOption(int opt, Object val) throws SocketException {
 259         if (isClosedOrPending()) {
 260             throw new SocketException("Socket Closed");
 261         }
 262         boolean on = true;
 263         switch (opt) {
 264             /* check type safety b4 going native.  These should never
 265              * fail, since only java.Socket* has access to
 266              * PlainSocketImpl.setOption().
 267              */
 268         case SO_LINGER:
 269             if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
 270                 throw new SocketException("Bad parameter for option");
 271             if (val instanceof Boolean) {
 272                 /* true only if disabling - enabling should be Integer */
 273                 on = false;
 274             }
 275             break;


 352         case SO_OOBINLINE:
 353             ret = socketGetOption(opt, null);
 354             return Boolean.valueOf(ret != -1);
 355         case SO_LINGER:
 356             ret = socketGetOption(opt, null);
 357             return (ret == -1) ? Boolean.FALSE: (Object)(ret);
 358         case SO_REUSEADDR:
 359             ret = socketGetOption(opt, null);
 360             return Boolean.valueOf(ret != -1);
 361         case SO_BINDADDR:
 362             InetAddressContainer in = new InetAddressContainer();
 363             ret = socketGetOption(opt, in);
 364             return in.addr;
 365         case SO_SNDBUF:
 366         case SO_RCVBUF:
 367             ret = socketGetOption(opt, null);
 368             return ret;
 369         case IP_TOS:
 370             try {
 371                 ret = socketGetOption(opt, null);
 372                 System.out.println("CHEGAR : ret: " + ret );
 373                 if (ret == -1) { // ipv6 tos
 374                     return trafficClass;
 375                 } else {
 376                     return ret;
 377                 }
 378             } catch (SocketException se) {
 379                     // TODO - should make better effort to read TOS or TCLASS
 380                     System.out.println("CHEGAR : swallowing: " + se );
 381                     return trafficClass; // ipv6 tos
 382             }
 383         case SO_KEEPALIVE:
 384             ret = socketGetOption(opt, null);
 385             return Boolean.valueOf(ret != -1);
 386         case SO_REUSEPORT:
 387             if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
 388                 throw new UnsupportedOperationException("unsupported option");
 389             }
 390             ret = socketGetOption(opt, null);
 391             return Boolean.valueOf(ret != -1);
 392         // should never get here
 393         default:
 394             return null;
 395         }
 396     }
 397 
 398     /**
 399      * The workhorse of the connection operation.  Tries several times to
 400      * establish a connection to the given <host, port>.  If unsuccessful,
 401      * throws an IOException indicating what went wrong.
 402      */
 403 
 404     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
 405         synchronized (fdLock) {
 406             if (!closePending && (server || !bound)) {
 407                 NetHooks.beforeTcpConnect(fd, address, port);
 408             }
 409         }
 410         try {
 411             acquireFD();
 412             try {
 413                 socketConnect(address, port, timeout);
 414                 /* socket may have been closed during poll/select */
 415                 synchronized (fdLock) {
 416                     if (closePending) {
 417                         throw new SocketException ("Socket closed");
 418                     }
 419                 }








 420             } finally {
 421                 releaseFD();
 422             }
 423         } catch (IOException e) {
 424             close();
 425             throw SocketExceptions.of(e, new InetSocketAddress(address, port));
 426         }
 427     }
 428 
 429     /**
 430      * Binds the socket to the specified address of the specified local port.
 431      * @param address the address
 432      * @param lport the port
 433      */
 434     protected synchronized void bind(InetAddress address, int lport)
 435         throws IOException
 436     {
 437        synchronized (fdLock) {
 438            if (!closePending && (server || !bound)) {
 439                NetHooks.beforeTcpBind(fd, address, lport);
 440            }
 441        }
 442        socketBind(address, lport);
 443        bound = true;



 444     }
 445 
 446     /**
 447      * Listens, for a specified amount of time, for connections.
 448      * @param count the amount of time to listen for connections
 449      */
 450     protected synchronized void listen(int count) throws IOException {
 451         socketListen(count);
 452     }
 453 
 454     /**
 455      * Accepts connections.
 456      * @param si the socket impl
 457      */
 458     protected void accept(SocketImpl si) throws IOException {
 459         si.fd = new FileDescriptor();
 460         acquireFD();
 461         try {
 462             socketAccept(si);
 463             bound = true;
 464             connected = true;
 465             //TODO REMOVE: try removing these lines to see it something will fail (setting of  bound & connected )
 466         } finally {
 467             releaseFD();
 468         }
 469         SocketCleanable.register(si.fd);
 470     }
 471 
 472     /**
 473      * Gets an InputStream for this socket.
 474      */
 475     protected synchronized InputStream getInputStream() throws IOException {
 476         synchronized (fdLock) {
 477             if (isClosedOrPending())
 478                 throw new IOException("Socket Closed");
 479             if (shut_rd)
 480                 throw new IOException("Socket input is shutdown");
 481             if (socketInputStream == null) {
 482                 PrivilegedExceptionAction<SocketInputStream> pa = () -> new SocketInputStream(this);
 483                 try {
 484                     socketInputStream = AccessController.doPrivileged(pa);
 485                 } catch (PrivilegedActionException e) {


 712     public int getTimeout() {
 713         return timeout;
 714     }
 715 
 716     /*
 717      * "Pre-close" a socket by dup'ing the file descriptor - this enables
 718      * the socket to be closed without releasing the file descriptor.
 719      */
 720     private void socketPreClose() throws IOException {
 721         socketClose0(true);
 722     }
 723 
 724     /*
 725      * Close the socket (and release the file descriptor).
 726      */
 727     protected void socketClose() throws IOException {
 728         SocketCleanable.unregister(fd);
 729         socketClose0(false);
 730     }
 731 
 732     abstract void socketCreate(boolean stream, boolean isServer) throws IOException;
 733     abstract void socketConnect(InetAddress address, int port, int timeout)
 734         throws IOException;
 735     abstract void socketBind(InetAddress address, int port)
 736         throws IOException;
 737     abstract void socketListen(int count)
 738         throws IOException;
 739     abstract void socketAccept(SocketImpl s)
 740         throws IOException;
 741     abstract int socketAvailable()
 742         throws IOException;
 743     abstract void socketClose0(boolean useDeferredClose)
 744         throws IOException;
 745     abstract void socketShutdown(int howto)
 746         throws IOException;
 747     abstract void socketSetOption(int cmd, boolean on, Object value)
 748         throws SocketException;
 749     abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
 750     abstract void socketSendUrgentData(int data)
 751         throws IOException;
 752 
< prev index next >