@@ -116,6 +116,11 @@ void TLSWrap::InitSSL() {
116116#endif // SSL_MODE_RELEASE_BUFFERS
117117
118118 SSL_set_app_data (ssl_.get (), this );
119+ // Using InfoCallback isn't how we are supposed to check handshake progress:
120+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420915993
121+ //
122+ // Note on when this gets called on various openssl versions:
123+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
119124 SSL_set_info_callback (ssl_.get (), SSLInfoCallback);
120125
121126 if (is_server ()) {
@@ -194,6 +199,9 @@ void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
194199
195200 // Send ClientHello handshake
196201 CHECK (wrap->is_client ());
202+ // Seems odd to read when when we want to send, but SSL_read() triggers a
203+ // handshake if a session isn't established, and handshake will cause
204+ // encrypted data to become available for output.
197205 wrap->ClearOut ();
198206 wrap->EncOut ();
199207}
@@ -243,7 +251,7 @@ void TLSWrap::EncOut() {
243251 return ;
244252
245253 // Wait for `newSession` callback to be invoked
246- if (is_waiting_new_session ())
254+ if (is_awaiting_new_session ())
247255 return ;
248256
249257 // Split-off queue
@@ -253,7 +261,7 @@ void TLSWrap::EncOut() {
253261 if (ssl_ == nullptr )
254262 return ;
255263
256- // No data to write
264+ // No encrypted output ready to write to the underlying stream.
257265 if (BIO_pending (enc_out_) == 0 ) {
258266 if (pending_cleartext_input_.empty ())
259267 InvokeQueued (0 );
@@ -442,13 +450,13 @@ void TLSWrap::ClearOut() {
442450}
443451
444452
445- bool TLSWrap::ClearIn () {
453+ void TLSWrap::ClearIn () {
446454 // Ignore cycling data if ClientHello wasn't yet parsed
447455 if (!hello_parser_.IsEnded ())
448- return false ;
456+ return ;
449457
450458 if (ssl_ == nullptr )
451- return false ;
459+ return ;
452460
453461 std::vector<uv_buf_t > buffers;
454462 buffers.swap (pending_cleartext_input_);
@@ -468,8 +476,9 @@ bool TLSWrap::ClearIn() {
468476
469477 // All written
470478 if (i == buffers.size ()) {
479+ // We wrote all the buffers, so no writes failed (written < 0 on failure).
471480 CHECK_GE (written, 0 );
472- return true ;
481+ return ;
473482 }
474483
475484 // Error or partial write
@@ -481,6 +490,8 @@ bool TLSWrap::ClearIn() {
481490 Local<Value> arg = GetSSLError (written, &err, &error_str);
482491 if (!arg.IsEmpty ()) {
483492 write_callback_scheduled_ = true ;
493+ // XXX(sam) Should forward an error object with .code/.function/.etc, if
494+ // possible.
484495 InvokeQueued (UV_EPROTO, error_str.c_str ());
485496 } else {
486497 // Push back the not-yet-written pending buffers into their queue.
@@ -491,7 +502,7 @@ bool TLSWrap::ClearIn() {
491502 buffers.end ());
492503 }
493504
494- return false ;
505+ return ;
495506}
496507
497508
@@ -547,6 +558,7 @@ void TLSWrap::ClearError() {
547558}
548559
549560
561+ // Called by StreamBase::Write() to request async write of clear text into SSL.
550562int TLSWrap::DoWrite (WriteWrap* w,
551563 uv_buf_t * bufs,
552564 size_t count,
@@ -560,18 +572,26 @@ int TLSWrap::DoWrite(WriteWrap* w,
560572 }
561573
562574 bool empty = true ;
563-
564- // Empty writes should not go through encryption process
565575 size_t i;
566- for (i = 0 ; i < count; i++)
576+ for (i = 0 ; i < count; i++) {
567577 if (bufs[i].len > 0 ) {
568578 empty = false ;
569579 break ;
570580 }
581+ }
582+
583+ // We want to trigger a Write() on the underlying stream to drive the stream
584+ // system, but don't want to encrypt empty buffers into a TLS frame, so see
585+ // if we can find something to Write().
586+ // First, call ClearOut(). It does an SSL_read(), which might cause handshake
587+ // or other internal messages to be encrypted. If it does, write them later
588+ // with EncOut().
589+ // If there is still no encrypted output, call Write(bufs) on the underlying
590+ // stream. Since the bufs are empty, it won't actually write non-TLS data
591+ // onto the socket, we just want the side-effects. After, make sure the
592+ // WriteWrap was accepted by the stream, or that we call Done() on it.
571593 if (empty) {
572594 ClearOut ();
573- // However, if there is any data that should be written to the socket,
574- // the callback should not be invoked immediately
575595 if (BIO_pending (enc_out_) == 0 ) {
576596 CHECK_NULL (current_empty_write_);
577597 current_empty_write_ = w;
@@ -591,7 +611,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
591611 CHECK_NULL (current_write_);
592612 current_write_ = w;
593613
594- // Write queued data
614+ // Write encrypted data to underlying stream and call Done().
595615 if (empty) {
596616 EncOut ();
597617 return 0 ;
@@ -610,17 +630,20 @@ int TLSWrap::DoWrite(WriteWrap* w,
610630 if (i != count) {
611631 int err;
612632 Local<Value> arg = GetSSLError (written, &err, &error_);
633+
634+ // If we stopped writing because of an error, it's fatal, discard the data.
613635 if (!arg.IsEmpty ()) {
614636 current_write_ = nullptr ;
615637 return UV_EPROTO;
616638 }
617639
640+ // Otherwise, save unwritten data so it can be written later by ClearIn().
618641 pending_cleartext_input_.insert (pending_cleartext_input_.end (),
619642 &bufs[i],
620643 &bufs[count]);
621644 }
622645
623- // Try writing data immediately
646+ // Write any encrypted/handshake output that may be ready.
624647 EncOut ();
625648
626649 return 0 ;
@@ -652,17 +675,20 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
652675 return ;
653676 }
654677
655- // Only client connections can receive data
656678 if (ssl_ == nullptr ) {
657679 EmitRead (UV_EPROTO);
658680 return ;
659681 }
660682
661- // Commit read data
683+ // Commit the amount of data actually read into the peeked/allocated buffer
684+ // from the underlying stream.
662685 crypto::NodeBIO* enc_in = crypto::NodeBIO::FromBIO (enc_in_);
663686 enc_in->Commit (nread);
664687
665- // Parse ClientHello first
688+ // Parse ClientHello first, if we need to. It's only parsed if session event
689+ // listeners are used on the server side. "ended" is the initial state, so
690+ // can mean parsing was never started, or that parsing is finished. Either
691+ // way, ended means we can give the buffered data to SSL.
666692 if (!hello_parser_.IsEnded ()) {
667693 size_t avail = 0 ;
668694 uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
0 commit comments