@@ -114,6 +114,11 @@ void TLSWrap::InitSSL() {
114114#endif // SSL_MODE_RELEASE_BUFFERS
115115
116116 SSL_set_app_data (ssl_.get (), this );
117+ // Using InfoCallback isn't how we are supposed to check handshake progress:
118+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420915993
119+ //
120+ // Note on when this gets called on various openssl versions:
121+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
117122 SSL_set_info_callback (ssl_.get (), SSLInfoCallback);
118123
119124 if (is_server ()) {
@@ -192,6 +197,9 @@ void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
192197
193198 // Send ClientHello handshake
194199 CHECK (wrap->is_client ());
200+ // Seems odd to read when when we want to send, but SSL_read() triggers a
201+ // handshake if a session isn't established, and handshake will cause
202+ // encrypted data to become available for output.
195203 wrap->ClearOut ();
196204 wrap->EncOut ();
197205}
@@ -246,7 +254,7 @@ void TLSWrap::EncOut() {
246254 return ;
247255
248256 // Wait for `newSession` callback to be invoked
249- if (is_waiting_new_session ())
257+ if (is_awaiting_new_session ())
250258 return ;
251259
252260 // Split-off queue
@@ -256,7 +264,7 @@ void TLSWrap::EncOut() {
256264 if (ssl_ == nullptr )
257265 return ;
258266
259- // No data to write
267+ // No encrypted output ready to write to the underlying stream.
260268 if (BIO_pending (enc_out_) == 0 ) {
261269 if (pending_cleartext_input_.empty ())
262270 InvokeQueued (0 );
@@ -443,13 +451,13 @@ void TLSWrap::ClearOut() {
443451}
444452
445453
446- bool TLSWrap::ClearIn () {
454+ void TLSWrap::ClearIn () {
447455 // Ignore cycling data if ClientHello wasn't yet parsed
448456 if (!hello_parser_.IsEnded ())
449- return false ;
457+ return ;
450458
451459 if (ssl_ == nullptr )
452- return false ;
460+ return ;
453461
454462 std::vector<uv_buf_t > buffers;
455463 buffers.swap (pending_cleartext_input_);
@@ -469,8 +477,9 @@ bool TLSWrap::ClearIn() {
469477
470478 // All written
471479 if (i == buffers.size ()) {
480+ // We wrote all the buffers, so no writes failed (written < 0 on failure).
472481 CHECK_GE (written, 0 );
473- return true ;
482+ return ;
474483 }
475484
476485 // Error or partial write
@@ -482,6 +491,8 @@ bool TLSWrap::ClearIn() {
482491 Local<Value> arg = GetSSLError (written, &err, &error_str);
483492 if (!arg.IsEmpty ()) {
484493 write_callback_scheduled_ = true ;
494+ // XXX(sam) Should forward an error object with .code/.function/.etc, if
495+ // possible.
485496 InvokeQueued (UV_EPROTO, error_str.c_str ());
486497 } else {
487498 // Push back the not-yet-written pending buffers into their queue.
@@ -492,7 +503,7 @@ bool TLSWrap::ClearIn() {
492503 buffers.end ());
493504 }
494505
495- return false ;
506+ return ;
496507}
497508
498509
@@ -548,6 +559,7 @@ void TLSWrap::ClearError() {
548559}
549560
550561
562+ // Called by StreamBase::Write() to request async write of clear text into SSL.
551563int TLSWrap::DoWrite (WriteWrap* w,
552564 uv_buf_t * bufs,
553565 size_t count,
@@ -561,18 +573,26 @@ int TLSWrap::DoWrite(WriteWrap* w,
561573 }
562574
563575 bool empty = true ;
564-
565- // Empty writes should not go through encryption process
566576 size_t i;
567- for (i = 0 ; i < count; i++)
577+ for (i = 0 ; i < count; i++) {
568578 if (bufs[i].len > 0 ) {
569579 empty = false ;
570580 break ;
571581 }
582+ }
583+
584+ // We want to trigger a Write() on the underlying stream to drive the stream
585+ // system, but don't want to encrypt empty buffers into a TLS frame, so see
586+ // if we can find something to Write().
587+ // First, call ClearOut(). It does an SSL_read(), which might cause handshake
588+ // or other internal messages to be encrypted. If it does, write them later
589+ // with EncOut().
590+ // If there is still no encrypted output, call Write(bufs) on the underlying
591+ // stream. Since the bufs are empty, it won't actually write non-TLS data
592+ // onto the socket, we just want the side-effects. After, make sure the
593+ // WriteWrap was accepted by the stream, or that we call Done() on it.
572594 if (empty) {
573595 ClearOut ();
574- // However, if there is any data that should be written to the socket,
575- // the callback should not be invoked immediately
576596 if (BIO_pending (enc_out_) == 0 ) {
577597 CHECK_NULL (current_empty_write_);
578598 current_empty_write_ = w;
@@ -592,7 +612,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
592612 CHECK_NULL (current_write_);
593613 current_write_ = w;
594614
595- // Write queued data
615+ // Write encrypted data to underlying stream and call Done().
596616 if (empty) {
597617 EncOut ();
598618 return 0 ;
@@ -611,17 +631,20 @@ int TLSWrap::DoWrite(WriteWrap* w,
611631 if (i != count) {
612632 int err;
613633 Local<Value> arg = GetSSLError (written, &err, &error_);
634+
635+ // If we stopped writing because of an error, it's fatal, discard the data.
614636 if (!arg.IsEmpty ()) {
615637 current_write_ = nullptr ;
616638 return UV_EPROTO;
617639 }
618640
641+ // Otherwise, save unwritten data so it can be written later by ClearIn().
619642 pending_cleartext_input_.insert (pending_cleartext_input_.end (),
620643 &bufs[i],
621644 &bufs[count]);
622645 }
623646
624- // Try writing data immediately
647+ // Write any encrypted/handshake output that may be ready.
625648 EncOut ();
626649
627650 return 0 ;
@@ -653,17 +676,20 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
653676 return ;
654677 }
655678
656- // Only client connections can receive data
657679 if (ssl_ == nullptr ) {
658680 EmitRead (UV_EPROTO);
659681 return ;
660682 }
661683
662- // Commit read data
684+ // Commit the amount of data actually read into the peeked/allocated buffer
685+ // from the underlying stream.
663686 crypto::NodeBIO* enc_in = crypto::NodeBIO::FromBIO (enc_in_);
664687 enc_in->Commit (nread);
665688
666- // Parse ClientHello first
689+ // Parse ClientHello first, if we need to. It's only parsed if session event
690+ // listeners are used on the server side. "ended" is the initial state, so
691+ // can mean parsing was never started, or that parsing is finished. Either
692+ // way, ended means we can give the buffered data to SSL.
667693 if (!hello_parser_.IsEnded ()) {
668694 size_t avail = 0 ;
669695 uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
0 commit comments