32
32
import org .neo4j .driver .internal .net .BoltServerAddress ;
33
33
import org .neo4j .driver .v1 .Logger ;
34
34
import org .neo4j .driver .internal .util .BytePrinter ;
35
+ import org .neo4j .driver .internal .util .BytePrinter ;
36
+ import org .neo4j .driver .v1 .Config .TrustStrategy ;
37
+ import org .neo4j .driver .v1 .Logger ;
35
38
import org .neo4j .driver .v1 .exceptions .ClientException ;
36
39
37
40
import static javax .net .ssl .SSLEngineResult .HandshakeStatus .FINISHED ;
@@ -67,8 +70,7 @@ public class TLSSocketChannel implements ByteChannel
67
70
public TLSSocketChannel ( BoltServerAddress address , SecurityPlan securityPlan , ByteChannel channel , Logger logger )
68
71
throws GeneralSecurityException , IOException
69
72
{
70
- this (channel , logger , createSSLEngine ( address , createSSLContext ( securityPlan ) ) );
71
-
73
+ this ( channel , logger , createSSLEngine ( address , securityPlan .sslContext () ) );
72
74
}
73
75
74
76
public TLSSocketChannel ( ByteChannel channel , Logger logger , SSLEngine sslEngine ) throws GeneralSecurityException , IOException
@@ -163,8 +165,8 @@ private HandshakeStatus runDelegatedTasks()
163
165
* To verify if deciphering is done successfully, we could check if any bytes has been read into {@code buffer},
164
166
* as the deciphered bytes will only be saved into {@code buffer} when deciphering is carried out successfully.
165
167
*
166
- * @param buffer
167
- * @return
168
+ * @param buffer to read data into.
169
+ * @return The status of the current handshake.
168
170
* @throws IOException
169
171
*/
170
172
private HandshakeStatus unwrap ( ByteBuffer buffer ) throws IOException
@@ -261,7 +263,7 @@ private HandshakeStatus unwrap( ByteBuffer buffer ) throws IOException
261
263
* a loop
262
264
*
263
265
* @param buffer contains the bytes to send to channel
264
- * @return
266
+ * @return The status of the current handshake
265
267
* @throws IOException
266
268
*/
267
269
private HandshakeStatus wrap ( ByteBuffer buffer ) throws IOException
@@ -277,7 +279,7 @@ private HandshakeStatus wrap( ByteBuffer buffer ) throws IOException
277
279
case OK :
278
280
handshakeStatus = runDelegatedTasks ();
279
281
cipherOut .flip ();
280
- while ( cipherOut .hasRemaining ())
282
+ while ( cipherOut .hasRemaining () )
281
283
{
282
284
channel .write ( cipherOut );
283
285
}
@@ -287,19 +289,30 @@ private HandshakeStatus wrap( ByteBuffer buffer ) throws IOException
287
289
// Enlarge the buffer and return the old status
288
290
int curNetSize = cipherOut .capacity ();
289
291
int netSize = sslEngine .getSession ().getPacketBufferSize ();
290
- if ( curNetSize >= netSize || buffer . capacity () > netSize )
292
+ if ( netSize > curNetSize )
291
293
{
292
- // TODO
293
- throw new ClientException (
294
- String .format ( "Failed to enlarge network buffer from %s to %s. This is either because the " +
295
- "new size is however less than the old size, or because the application " +
296
- "buffer size %s is so big that the application data still cannot fit into the " +
297
- "new network buffer." , curNetSize , netSize , buffer .capacity () ) );
294
+ // enlarge the peer application data buffer
295
+ cipherOut = ByteBuffer .allocate ( netSize );
296
+ logger .debug ( "Enlarged network output buffer from %s to %s. " +
297
+ "This operation should be a rare operation." , curNetSize , netSize );
298
+ }
299
+ else
300
+ {
301
+ // flush as much data as possible
302
+ cipherOut .flip ();
303
+ int written = channel .write ( cipherOut );
304
+ if (written == 0 )
305
+ {
306
+ throw new ClientException (
307
+ String .format (
308
+ "Failed to enlarge network buffer from %s to %s. This is either because the " +
309
+ "new size is however less than the old size, or because the application " +
310
+ "buffer size %s is so big that the application data still cannot fit into the " +
311
+ "new network buffer." , curNetSize , netSize , buffer .capacity () ) );
312
+ }
313
+ cipherOut .compact ();
314
+ logger .debug ( "Network output buffer couldn't be enlarged, flushing data to the channel instead." );
298
315
}
299
-
300
- cipherOut = ByteBuffer .allocate ( netSize );
301
- logger .debug ( "Enlarged network output buffer from %s to %s. " +
302
- "This operation should be a rare operation." , curNetSize , netSize );
303
316
break ;
304
317
default :
305
318
throw new ClientException ( "Got unexpected status " + status );
@@ -320,9 +333,9 @@ private HandshakeStatus wrap( ByteBuffer buffer ) throws IOException
320
333
* After the method call, the new position of {@code from.pos} will be {@code from.pos + p}, and similarly,
321
334
* the new position of {@code to.pos} will be {@code to.pos + p}
322
335
*
323
- * @param from
324
- * @param to
325
- * @return
336
+ * @param from buffer to copy from
337
+ * @param to buffer to copy to
338
+ * @return the number of transferred bytes
326
339
*/
327
340
static int bufferCopy ( ByteBuffer from , ByteBuffer to )
328
341
{
@@ -339,25 +352,10 @@ static int bufferCopy( ByteBuffer from, ByteBuffer to )
339
352
return maxTransfer ;
340
353
}
341
354
342
- /**
343
- * Create an SSLContext based on a given SecurityPlan.
344
- *
345
- * @param securityPlan
346
- * @return
347
- * @throws GeneralSecurityException
348
- * @throws IOException
349
- */
350
- private static SSLContext createSSLContext ( SecurityPlan securityPlan ) throws GeneralSecurityException , IOException
351
- {
352
- SSLContext sslContext = SSLContext .getInstance ( "TLS" );
353
- sslContext .init ( new KeyManager [0 ], securityPlan .trustManagers (), null );
354
- return sslContext ;
355
- }
356
-
357
355
/**
358
356
* Create SSLEngine with the SSLContext just created.
359
- * @param address
360
- * @param sslContext
357
+ * @param address the host to connect to
358
+ * @param sslContext the current ssl context
361
359
*/
362
360
private static SSLEngine createSSLEngine ( BoltServerAddress address , SSLContext sslContext )
363
361
{
@@ -445,10 +443,10 @@ public void close() throws IOException
445
443
channel .close ();
446
444
logger .debug ( "~~ [CLOSED SECURE CHANNEL]" );
447
445
}
448
- catch ( IOException e )
446
+ catch ( IOException e )
449
447
{
450
448
// Treat this as ok - the connection is closed, even if the TLS session did not exit cleanly.
451
- logger .warn ( "TLS socket could not be closed cleanly: '" + e .getMessage ()+ "'" , e );
449
+ logger .warn ( "TLS socket could not be closed cleanly: '" + e .getMessage () + "'" , e );
452
450
}
453
451
}
454
452
0 commit comments