@@ -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}
@@ -248,7 +256,7 @@ void TLSWrap::EncOut() {
248256 return ;
249257
250258 // Wait for `newSession` callback to be invoked
251- if (is_waiting_new_session ())
259+ if (is_awaiting_new_session ())
252260 return ;
253261
254262 // Split-off queue
@@ -258,7 +266,7 @@ void TLSWrap::EncOut() {
258266 if (ssl_ == nullptr )
259267 return ;
260268
261- // No data to write
269+ // No encrypted output ready to write to the underlying stream.
262270 if (BIO_pending (enc_out_) == 0 ) {
263271 if (pending_cleartext_input_.empty ())
264272 InvokeQueued (0 );
@@ -480,13 +488,13 @@ void TLSWrap::ClearOut() {
480488}
481489
482490
483- bool TLSWrap::ClearIn () {
491+ void TLSWrap::ClearIn () {
484492 // Ignore cycling data if ClientHello wasn't yet parsed
485493 if (!hello_parser_.IsEnded ())
486- return false ;
494+ return ;
487495
488496 if (ssl_ == nullptr )
489- return false ;
497+ return ;
490498
491499 std::vector<uv_buf_t > buffers;
492500 buffers.swap (pending_cleartext_input_);
@@ -506,8 +514,9 @@ bool TLSWrap::ClearIn() {
506514
507515 // All written
508516 if (i == buffers.size ()) {
517+ // We wrote all the buffers, so no writes failed (written < 0 on failure).
509518 CHECK_GE (written, 0 );
510- return true ;
519+ return ;
511520 }
512521
513522 // Error or partial write
@@ -519,6 +528,8 @@ bool TLSWrap::ClearIn() {
519528 Local<Value> arg = GetSSLError (written, &err, &error_str);
520529 if (!arg.IsEmpty ()) {
521530 write_callback_scheduled_ = true ;
531+ // XXX(sam) Should forward an error object with .code/.function/.etc, if
532+ // possible.
522533 InvokeQueued (UV_EPROTO, error_str.c_str ());
523534 } else {
524535 // Push back the not-yet-written pending buffers into their queue.
@@ -529,7 +540,7 @@ bool TLSWrap::ClearIn() {
529540 buffers.end ());
530541 }
531542
532- return false ;
543+ return ;
533544}
534545
535546
@@ -585,6 +596,7 @@ void TLSWrap::ClearError() {
585596}
586597
587598
599+ // Called by StreamBase::Write() to request async write of clear text into SSL.
588600int TLSWrap::DoWrite (WriteWrap* w,
589601 uv_buf_t * bufs,
590602 size_t count,
@@ -598,18 +610,26 @@ int TLSWrap::DoWrite(WriteWrap* w,
598610 }
599611
600612 bool empty = true ;
601-
602- // Empty writes should not go through encryption process
603613 size_t i;
604- for (i = 0 ; i < count; i++)
614+ for (i = 0 ; i < count; i++) {
605615 if (bufs[i].len > 0 ) {
606616 empty = false ;
607617 break ;
608618 }
619+ }
620+
621+ // We want to trigger a Write() on the underlying stream to drive the stream
622+ // system, but don't want to encrypt empty buffers into a TLS frame, so see
623+ // if we can find something to Write().
624+ // First, call ClearOut(). It does an SSL_read(), which might cause handshake
625+ // or other internal messages to be encrypted. If it does, write them later
626+ // with EncOut().
627+ // If there is still no encrypted output, call Write(bufs) on the underlying
628+ // stream. Since the bufs are empty, it won't actually write non-TLS data
629+ // onto the socket, we just want the side-effects. After, make sure the
630+ // WriteWrap was accepted by the stream, or that we call Done() on it.
609631 if (empty) {
610632 ClearOut ();
611- // However, if there is any data that should be written to the socket,
612- // the callback should not be invoked immediately
613633 if (BIO_pending (enc_out_) == 0 ) {
614634 CHECK_NULL (current_empty_write_);
615635 current_empty_write_ = w;
@@ -629,7 +649,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
629649 CHECK_NULL (current_write_);
630650 current_write_ = w;
631651
632- // Write queued data
652+ // Write encrypted data to underlying stream and call Done().
633653 if (empty) {
634654 EncOut ();
635655 return 0 ;
@@ -648,17 +668,20 @@ int TLSWrap::DoWrite(WriteWrap* w,
648668 if (i != count) {
649669 int err;
650670 Local<Value> arg = GetSSLError (written, &err, &error_);
671+
672+ // If we stopped writing because of an error, it's fatal, discard the data.
651673 if (!arg.IsEmpty ()) {
652674 current_write_ = nullptr ;
653675 return UV_EPROTO;
654676 }
655677
678+ // Otherwise, save unwritten data so it can be written later by ClearIn().
656679 pending_cleartext_input_.insert (pending_cleartext_input_.end (),
657680 &bufs[i],
658681 &bufs[count]);
659682 }
660683
661- // Try writing data immediately
684+ // Write any encrypted/handshake output that may be ready.
662685 EncOut ();
663686
664687 return 0 ;
@@ -690,17 +713,20 @@ void TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
690713 return ;
691714 }
692715
693- // Only client connections can receive data
694716 if (ssl_ == nullptr ) {
695717 EmitRead (UV_EPROTO);
696718 return ;
697719 }
698720
699- // Commit read data
721+ // Commit the amount of data actually read into the peeked/allocated buffer
722+ // from the underlying stream.
700723 crypto::NodeBIO* enc_in = crypto::NodeBIO::FromBIO (enc_in_);
701724 enc_in->Commit (nread);
702725
703- // Parse ClientHello first
726+ // Parse ClientHello first, if we need to. It's only parsed if session event
727+ // listeners are used on the server side. "ended" is the initial state, so
728+ // can mean parsing was never started, or that parsing is finished. Either
729+ // way, ended means we can give the buffered data to SSL.
704730 if (!hello_parser_.IsEnded ()) {
705731 size_t avail = 0 ;
706732 uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
0 commit comments