@@ -115,6 +115,11 @@ void TLSWrap::InitSSL() {
115115#endif // SSL_MODE_RELEASE_BUFFERS
116116
117117 SSL_set_app_data (ssl_.get (), this );
118+ // Using InfoCallback isn't how we are supposed to check handshake progress:
119+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420915993
120+ //
121+ // Note on when this gets called on various openssl versions:
122+ // https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
118123 SSL_set_info_callback (ssl_.get (), SSLInfoCallback);
119124
120125 if (is_server ()) {
@@ -193,6 +198,9 @@ void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
193198
194199 // Send ClientHello handshake
195200 CHECK (wrap->is_client ());
201+ // Seems odd to read when when we want to send, but SSL_read() triggers a
202+ // handshake if a session isn't established, and handshake will cause
203+ // encrypted data to become available for output.
196204 wrap->ClearOut ();
197205 wrap->EncOut ();
198206}
@@ -247,7 +255,7 @@ void TLSWrap::EncOut() {
247255 return ;
248256
249257 // Wait for `newSession` callback to be invoked
250- if (is_waiting_new_session ())
258+ if (is_awaiting_new_session ())
251259 return ;
252260
253261 // Split-off queue
@@ -257,7 +265,7 @@ void TLSWrap::EncOut() {
257265 if (ssl_ == nullptr )
258266 return ;
259267
260- // No data to write
268+ // No encrypted output ready to write to the underlying stream.
261269 if (BIO_pending (enc_out_) == 0 ) {
262270 if (pending_cleartext_input_.empty ())
263271 InvokeQueued (0 );
@@ -479,13 +487,13 @@ void TLSWrap::ClearOut() {
479487}
480488
481489
482- bool TLSWrap::ClearIn () {
490+ void TLSWrap::ClearIn () {
483491 // Ignore cycling data if ClientHello wasn't yet parsed
484492 if (!hello_parser_.IsEnded ())
485- return false ;
493+ return ;
486494
487495 if (ssl_ == nullptr )
488- return false ;
496+ return ;
489497
490498 std::vector<uv_buf_t > buffers;
491499 buffers.swap (pending_cleartext_input_);
@@ -505,8 +513,9 @@ bool TLSWrap::ClearIn() {
505513
506514 // All written
507515 if (i == buffers.size ()) {
516+ // We wrote all the buffers, so no writes failed (written < 0 on failure).
508517 CHECK_GE (written, 0 );
509- return true ;
518+ return ;
510519 }
511520
512521 // Error or partial write
@@ -518,6 +527,8 @@ bool TLSWrap::ClearIn() {
518527 Local<Value> arg = GetSSLError (written, &err, &error_str);
519528 if (!arg.IsEmpty ()) {
520529 write_callback_scheduled_ = true ;
530+ // XXX(sam) Should forward an error object with .code/.function/.etc, if
531+ // possible.
521532 InvokeQueued (UV_EPROTO, error_str.c_str ());
522533 } else {
523534 // Push back the not-yet-written pending buffers into their queue.
@@ -528,7 +539,7 @@ bool TLSWrap::ClearIn() {
528539 buffers.end ());
529540 }
530541
531- return false ;
542+ return ;
532543}
533544
534545
@@ -584,6 +595,7 @@ void TLSWrap::ClearError() {
584595}
585596
586597
598+ // Called by StreamBase::Write() to request async write of clear text into SSL.
587599int TLSWrap::DoWrite (WriteWrap* w,
588600 uv_buf_t * bufs,
589601 size_t count,
@@ -597,18 +609,26 @@ int TLSWrap::DoWrite(WriteWrap* w,
597609 }
598610
599611 bool empty = true ;
600-
601- // Empty writes should not go through encryption process
602612 size_t i;
603- for (i = 0 ; i < count; i++)
613+ for (i = 0 ; i < count; i++) {
604614 if (bufs[i].len > 0 ) {
605615 empty = false ;
606616 break ;
607617 }
618+ }
619+
620+ // We want to trigger a Write() on the underlying stream to drive the stream
621+ // system, but don't want to encrypt empty buffers into a TLS frame, so see
622+ // if we can find something to Write().
623+ // First, call ClearOut(). It does an SSL_read(), which might cause handshake
624+ // or other internal messages to be encrypted. If it does, write them later
625+ // with EncOut().
626+ // If there is still no encrypted output, call Write(bufs) on the underlying
627+ // stream. Since the bufs are empty, it won't actually write non-TLS data
628+ // onto the socket, we just want the side-effects. After, make sure the
629+ // WriteWrap was accepted by the stream, or that we call Done() on it.
608630 if (empty) {
609631 ClearOut ();
610- // However, if there is any data that should be written to the socket,
611- // the callback should not be invoked immediately
612632 if (BIO_pending (enc_out_) == 0 ) {
613633 CHECK_NULL (current_empty_write_);
614634 current_empty_write_ = w;
@@ -628,7 +648,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
628648 CHECK_NULL (current_write_);
629649 current_write_ = w;
630650
631- // Write queued data
651+ // Write encrypted data to underlying stream and call Done().
632652 if (empty) {
633653 EncOut ();
634654 return 0 ;
@@ -647,17 +667,20 @@ int TLSWrap::DoWrite(WriteWrap* w,
647667 if (i != count) {
648668 int err;
649669 Local<Value> arg = GetSSLError (written, &err, &error_);
670+
671+ // If we stopped writing because of an error, it's fatal, discard the data.
650672 if (!arg.IsEmpty ()) {
651673 current_write_ = nullptr ;
652674 return UV_EPROTO;
653675 }
654676
677+ // Otherwise, save unwritten data so it can be written later by ClearIn().
655678 pending_cleartext_input_.insert (pending_cleartext_input_.end (),
656679 &bufs[i],
657680 &bufs[count]);
658681 }
659682
660- // Try writing data immediately
683+ // Write any encrypted/handshake output that may be ready.
661684 EncOut ();
662685
663686 return 0 ;
@@ -689,17 +712,20 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
689712 return ;
690713 }
691714
692- // Only client connections can receive data
693715 if (ssl_ == nullptr ) {
694716 EmitRead (UV_EPROTO);
695717 return ;
696718 }
697719
698- // Commit read data
720+ // Commit the amount of data actually read into the peeked/allocated buffer
721+ // from the underlying stream.
699722 crypto::NodeBIO* enc_in = crypto::NodeBIO::FromBIO (enc_in_);
700723 enc_in->Commit (nread);
701724
702- // Parse ClientHello first
725+ // Parse ClientHello first, if we need to. It's only parsed if session event
726+ // listeners are used on the server side. "ended" is the initial state, so
727+ // can mean parsing was never started, or that parsing is finished. Either
728+ // way, ended means we can give the buffered data to SSL.
703729 if (!hello_parser_.IsEnded ()) {
704730 size_t avail = 0 ;
705731 uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
0 commit comments