src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
branchniosocketimpl-branch
changeset 57188 1f2101ee432d
parent 57187 056911ad3ee7
child 57189 c56554b46dec
equal deleted inserted replaced
57187:056911ad3ee7 57188:1f2101ee432d
   125     private volatile int timeout;
   125     private volatile int timeout;
   126 
   126 
   127     // flags to indicate if the connection is shutdown for input and output
   127     // flags to indicate if the connection is shutdown for input and output
   128     private volatile boolean isInputClosed;
   128     private volatile boolean isInputClosed;
   129     private volatile boolean isOutputClosed;
   129     private volatile boolean isOutputClosed;
   130 
       
   131     // socket input/output streams
       
   132     private volatile InputStream in;
       
   133     private volatile OutputStream out;
       
   134     private static final VarHandle IN, OUT;
       
   135     static {
       
   136         try {
       
   137             MethodHandles.Lookup l = MethodHandles.lookup();
       
   138             IN = l.findVarHandle(NioSocketImpl.class, "in", InputStream.class);
       
   139             OUT = l.findVarHandle(NioSocketImpl.class, "out", OutputStream.class);
       
   140         } catch (Exception e) {
       
   141             throw new InternalError(e);
       
   142         }
       
   143     }
       
   144 
   130 
   145     /**
   131     /**
   146      * Creates a instance of this SocketImpl.
   132      * Creates a instance of this SocketImpl.
   147      * @param server true if this is a SocketImpl for a ServerSocket
   133      * @param server true if this is a SocketImpl for a ServerSocket
   148      */
   134      */
   753         }
   739         }
   754     }
   740     }
   755 
   741 
   756     @Override
   742     @Override
   757     protected InputStream getInputStream() {
   743     protected InputStream getInputStream() {
   758         InputStream in = this.in;
   744         return new InputStream() {
   759         if (in == null) {
   745             // EOF or connection reset detected, not thread safe
   760             in = new SocketInputStream(this);
   746             private boolean eof, reset;
   761             if (!IN.compareAndSet(this, null, in)) {
   747             @Override
   762                 in = this.in;
   748             public int read() throws IOException {
   763             }
   749                 byte[] a = new byte[1];
   764         }
   750                 int n = read(a, 0, 1);
   765         return in;
   751                 return (n > 0) ? (a[0] & 0xff) : -1;
   766     }
   752             }
   767 
   753             @Override
   768     private static class SocketInputStream extends InputStream {
   754             public int read(byte[] b, int off, int len) throws IOException {
   769         private final NioSocketImpl impl;
   755                 Objects.checkFromIndexSize(off, len, b.length);
   770         // EOF or connection reset detected, not thread safe
   756                 if (eof) {
   771         private boolean eof, reset;
   757                     return -1;
   772         SocketInputStream(NioSocketImpl impl) {
   758                 } else if (reset) {
   773             this.impl = impl;
       
   774         }
       
   775         @Override
       
   776         public int read() throws IOException {
       
   777             byte[] a = new byte[1];
       
   778             int n = read(a, 0, 1);
       
   779             return (n > 0) ? (a[0] & 0xff) : -1;
       
   780         }
       
   781         @Override
       
   782         public int read(byte[] b, int off, int len) throws IOException {
       
   783             Objects.checkFromIndexSize(off, len, b.length);
       
   784             if (eof) {
       
   785                 return -1;
       
   786             } else if (reset) {
       
   787                 throw new SocketException("Connection reset");
       
   788             } else if (len == 0) {
       
   789                 return 0;
       
   790             } else {
       
   791                 try {
       
   792                     // read up to MAX_BUFFER_SIZE bytes
       
   793                     int size = Math.min(len, MAX_BUFFER_SIZE);
       
   794                     int n = impl.read(b, off, size);
       
   795                     if (n == -1)
       
   796                         eof = true;
       
   797                     return n;
       
   798                 } catch (ConnectionResetException e) {
       
   799                     reset = true;
       
   800                     throw new SocketException("Connection reset");
   759                     throw new SocketException("Connection reset");
   801                 } catch (SocketTimeoutException e) {
   760                 } else if (len == 0) {
   802                     throw e;
   761                     return 0;
   803                 } catch (IOException ioe) {
   762                 } else {
   804                     throw new SocketException(ioe.getMessage());
   763                     try {
   805                 }
   764                         // read up to MAX_BUFFER_SIZE bytes
   806             }
   765                         int size = Math.min(len, MAX_BUFFER_SIZE);
   807         }
   766                         int n = NioSocketImpl.this.read(b, off, size);
   808         @Override
   767                         if (n == -1)
   809         public int available() throws IOException {
   768                             eof = true;
   810             return impl.available();
   769                         return n;
   811         }
   770                     } catch (ConnectionResetException e) {
   812         @Override
   771                         reset = true;
   813         public void close() throws IOException {
   772                         throw new SocketException("Connection reset");
   814             impl.close();
   773                     } catch (SocketTimeoutException e) {
   815         }
   774                         throw e;
       
   775                     } catch (IOException ioe) {
       
   776                         throw new SocketException(ioe.getMessage());
       
   777                     }
       
   778                 }
       
   779             }
       
   780             @Override
       
   781             public int available() throws IOException {
       
   782                 return NioSocketImpl.this.available();
       
   783             }
       
   784             @Override
       
   785             public void close() throws IOException {
       
   786                 NioSocketImpl.this.close();
       
   787             }
       
   788         };
   816     }
   789     }
   817 
   790 
   818     @Override
   791     @Override
   819     protected OutputStream getOutputStream() {
   792     protected OutputStream getOutputStream() {
   820         OutputStream out = this.out;
   793         return new OutputStream() {
   821         if (out == null) {
   794             @Override
   822             out = new SocketOutputStream(this);
   795             public void write(int b) throws IOException {
   823             if (!OUT.compareAndSet(this, null, out)) {
   796                 byte[] a = new byte[]{(byte) b};
   824                 out = this.out;
   797                 write(a, 0, 1);
   825             }
   798             }
   826         }
   799             @Override
   827         return out;
   800             public void write(byte[] b, int off, int len) throws IOException {
   828     }
   801                 Objects.checkFromIndexSize(off, len, b.length);
   829 
   802                 if (len > 0) {
   830     private static class SocketOutputStream extends OutputStream {
   803                     try {
   831         private final NioSocketImpl impl;
   804                         int pos = off;
   832         SocketOutputStream(NioSocketImpl impl) {
   805                         int end = off + len;
   833             this.impl = impl;
   806                         while (pos < end) {
   834         }
   807                             // write up to MAX_BUFFER_SIZE bytes
   835         @Override
   808                             int size = Math.min((end - pos), MAX_BUFFER_SIZE);
   836         public void write(int b) throws IOException {
   809                             int n = NioSocketImpl.this.write(b, pos, size);
   837             byte[] a = new byte[]{(byte) b};
   810                             pos += n;
   838             write(a, 0, 1);
   811                         }
   839         }
   812                     } catch (IOException ioe) {
   840         @Override
   813                         throw new SocketException(ioe.getMessage());
   841         public void write(byte[] b, int off, int len) throws IOException {
       
   842             Objects.checkFromIndexSize(off, len, b.length);
       
   843             if (len > 0) {
       
   844                 try {
       
   845                     int pos = off;
       
   846                     int end = off + len;
       
   847                     while (pos < end) {
       
   848                         // write up to MAX_BUFFER_SIZE bytes
       
   849                         int size = Math.min((end - pos), MAX_BUFFER_SIZE);
       
   850                         int n = impl.write(b, pos, size);
       
   851                         pos += n;
       
   852                     }
   814                     }
   853                 } catch (IOException ioe) {
   815                 }
   854                     throw new SocketException(ioe.getMessage());
   816             }
   855                 }
   817 
   856             }
   818             @Override
   857         }
   819             public void close() throws IOException {
   858         @Override
   820                 NioSocketImpl.this.close();
   859         public void close() throws IOException {
   821             }
   860             impl.close();
   822         };
   861         }
       
   862     }
   823     }
   863 
   824 
   864     @Override
   825     @Override
   865     protected int available() throws IOException {
   826     protected int available() throws IOException {
   866         readLock.lock();
   827         readLock.lock();
   988                     timeout = i;
   949                     timeout = i;
   989                     break;
   950                     break;
   990                 }
   951                 }
   991                 case IP_TOS: {
   952                 case IP_TOS: {
   992                     int i = intValue(value, "IP_TOS");
   953                     int i = intValue(value, "IP_TOS");
   993                     var IP_TOS = StandardSocketOptions.IP_TOS;
   954                     Net.setSocketOption(fd, family(), StandardSocketOptions.IP_TOS, i);
   994                     Net.setSocketOption(fd, family(), IP_TOS, i);
       
   995                     trafficClass = i;
   955                     trafficClass = i;
   996                     break;
   956                     break;
   997                 }
   957                 }
   998                 case TCP_NODELAY: {
   958                 case TCP_NODELAY: {
   999                     boolean b = booleanValue(value, "TCP_NODELAY");
   959                     boolean b = booleanValue(value, "TCP_NODELAY");