< prev index next >

src/share/classes/sun/security/ssl/SSLSocketImpl.java

Print this page
rev 14406 : 8239798: SSLSocket closes socket both socket endpoints on a SocketTimeoutException
Reviewed-by: xuelei
Contributed-by: alexey@azul.com verghese@amazon.com


 417         }
 418 
 419         handshakeLock.lock();
 420         try {
 421             // double check the context status
 422             if (conContext.isBroken || conContext.isInboundClosed() ||
 423                     conContext.isOutboundClosed()) {
 424                 throw new SocketException("Socket has been closed or broken");
 425             }
 426 
 427             try {
 428                 conContext.kickstart();
 429 
 430                 // All initial handshaking goes through this operation until we
 431                 // have a valid SSL connection.
 432                 //
 433                 // Handle handshake messages only, need no application data.
 434                 if (!conContext.isNegotiated) {
 435                     readHandshakeRecord();
 436                 }


 437             } catch (IOException ioe) {
 438                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
 439                     "Couldn't kickstart handshaking", ioe);
 440             } catch (Exception oe) {    // including RuntimeException
 441                 handleException(oe);
 442             }
 443         } finally {
 444             handshakeLock.unlock();
 445         }
 446     }
 447 
 448     @Override
 449     public void setUseClientMode(boolean mode) {
 450         socketLock.lock();
 451         try {
 452             conContext.setUseClientMode(mode);
 453         } finally {
 454             socketLock.unlock();
 455         }
 456     }


1278         try {
1279             return conContext.sslConfig.socketAPSelector;
1280         } finally {
1281             socketLock.unlock();
1282         }
1283     }
1284 
1285     /**
1286      * Read the initial handshake records.
1287      */
1288     private int readHandshakeRecord() throws IOException {
1289         while (!conContext.isInboundClosed()) {
1290             try {
1291                 Plaintext plainText = decode(null);
1292                 if ((plainText.contentType == ContentType.HANDSHAKE.id) &&
1293                         conContext.isNegotiated) {
1294                     return 0;
1295                 }
1296             } catch (SSLException ssle) {
1297                 throw ssle;



1298             } catch (IOException ioe) {
1299                 if (!(ioe instanceof SSLException)) {
1300                     throw new SSLException("readHandshakeRecord", ioe);
1301                 } else {
1302                     throw ioe;
1303                 }
1304             }
1305         }
1306 
1307         return -1;
1308     }
1309 
1310     /**
1311      * Read application data record. Used by AppInputStream only, but defined
1312      * here so as to use the socket level synchronization.
1313      *
1314      * Note that the connection guarantees that handshake, alert, and change
1315      * cipher spec data streams are handled as they arrive, so we never see
1316      * them here.
1317      *
1318      * Note: Please be careful about the synchronization, and don't use this
1319      * method other than in the AppInputStream class!
1320      */
1321     private ByteBuffer readApplicationRecord(
1322             ByteBuffer buffer) throws IOException {
1323         while (!conContext.isInboundClosed()) {


1344             }
1345 
1346             if (inLen > buffer.remaining()) {
1347                 buffer = ByteBuffer.allocate(inLen);
1348             }
1349 
1350             try {
1351                 Plaintext plainText;
1352                 socketLock.lock();
1353                 try {
1354                     plainText = decode(buffer);
1355                 } finally {
1356                     socketLock.unlock();
1357                 }
1358                 if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
1359                         buffer.position() > 0) {
1360                     return buffer;
1361                 }
1362             } catch (SSLException ssle) {
1363                 throw ssle;



1364             } catch (IOException ioe) {
1365                 if (!(ioe instanceof SSLException)) {
1366                     throw new SSLException("readApplicationRecord", ioe);
1367                 } else {
1368                     throw ioe;
1369                 }
1370             }
1371         }
1372 
1373         //
1374         // couldn't read, due to some kind of error
1375         //
1376         return null;
1377     }
1378 
1379     private Plaintext decode(ByteBuffer destination) throws IOException {
1380         Plaintext plainText;
1381         try {
1382             if (destination == null) {
1383                 plainText = SSLTransport.decode(conContext,




 417         }
 418 
 419         handshakeLock.lock();
 420         try {
 421             // double check the context status
 422             if (conContext.isBroken || conContext.isInboundClosed() ||
 423                     conContext.isOutboundClosed()) {
 424                 throw new SocketException("Socket has been closed or broken");
 425             }
 426 
 427             try {
 428                 conContext.kickstart();
 429 
 430                 // All initial handshaking goes through this operation until we
 431                 // have a valid SSL connection.
 432                 //
 433                 // Handle handshake messages only, need no application data.
 434                 if (!conContext.isNegotiated) {
 435                     readHandshakeRecord();
 436                 }
 437             } catch (InterruptedIOException iioe) {
 438                 handleException(iioe);
 439             } catch (IOException ioe) {
 440                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
 441                     "Couldn't kickstart handshaking", ioe);
 442             } catch (Exception oe) {    // including RuntimeException
 443                 handleException(oe);
 444             }
 445         } finally {
 446             handshakeLock.unlock();
 447         }
 448     }
 449 
 450     @Override
 451     public void setUseClientMode(boolean mode) {
 452         socketLock.lock();
 453         try {
 454             conContext.setUseClientMode(mode);
 455         } finally {
 456             socketLock.unlock();
 457         }
 458     }


1280         try {
1281             return conContext.sslConfig.socketAPSelector;
1282         } finally {
1283             socketLock.unlock();
1284         }
1285     }
1286 
1287     /**
1288      * Read the initial handshake records.
1289      */
1290     private int readHandshakeRecord() throws IOException {
1291         while (!conContext.isInboundClosed()) {
1292             try {
1293                 Plaintext plainText = decode(null);
1294                 if ((plainText.contentType == ContentType.HANDSHAKE.id) &&
1295                         conContext.isNegotiated) {
1296                     return 0;
1297                 }
1298             } catch (SSLException ssle) {
1299                 throw ssle;
1300             } catch (InterruptedIOException iioe) {
1301                 // don't change exception in case of timeouts or interrupts
1302                 throw iioe;
1303             } catch (IOException ioe) {

1304                 throw new SSLException("readHandshakeRecord", ioe);



1305             }
1306         }
1307 
1308         return -1;
1309     }
1310 
1311     /**
1312      * Read application data record. Used by AppInputStream only, but defined
1313      * here so as to use the socket level synchronization.
1314      *
1315      * Note that the connection guarantees that handshake, alert, and change
1316      * cipher spec data streams are handled as they arrive, so we never see
1317      * them here.
1318      *
1319      * Note: Please be careful about the synchronization, and don't use this
1320      * method other than in the AppInputStream class!
1321      */
1322     private ByteBuffer readApplicationRecord(
1323             ByteBuffer buffer) throws IOException {
1324         while (!conContext.isInboundClosed()) {


1345             }
1346 
1347             if (inLen > buffer.remaining()) {
1348                 buffer = ByteBuffer.allocate(inLen);
1349             }
1350 
1351             try {
1352                 Plaintext plainText;
1353                 socketLock.lock();
1354                 try {
1355                     plainText = decode(buffer);
1356                 } finally {
1357                     socketLock.unlock();
1358                 }
1359                 if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
1360                         buffer.position() > 0) {
1361                     return buffer;
1362                 }
1363             } catch (SSLException ssle) {
1364                 throw ssle;
1365             } catch (InterruptedIOException iioe) {
1366                 // don't change exception in case of timeouts or interrupts
1367                 throw iioe;
1368             } catch (IOException ioe) {
1369                 if (!(ioe instanceof SSLException)) {
1370                     throw new SSLException("readApplicationRecord", ioe);
1371                 } else {
1372                     throw ioe;
1373                 }
1374             }
1375         }
1376 
1377         //
1378         // couldn't read, due to some kind of error
1379         //
1380         return null;
1381     }
1382 
1383     private Plaintext decode(ByteBuffer destination) throws IOException {
1384         Plaintext plainText;
1385         try {
1386             if (destination == null) {
1387                 plainText = SSLTransport.decode(conContext,


< prev index next >