From 014ab77276378ed9be918e77cf07fb7e6ad6b424 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Fri, 16 Aug 2013 01:30:47 +0400 Subject: [PATCH] crypto: try moving read head in Peek() Otherwise it might get stall (`Peek()` will return zero-length chunk) in following situation: 1. `Write(kBufferLength)` 2. `Read(kBufferLength)` 3. `Write(anything)` 4. `Peek()` => `len=0` --- src/node_crypto_bio.cc | 34 ++++++++++++++++++++++++---------- src/node_crypto_bio.h | 3 +++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/node_crypto_bio.cc b/src/node_crypto_bio.cc index f5c012d..05a4b5f 100644 --- a/src/node_crypto_bio.cc +++ b/src/node_crypto_bio.cc @@ -191,6 +191,25 @@ long NodeBIO::Ctrl(BIO* bio, int cmd, long num, void* ptr) { } +void NodeBIO::TryMoveReadHead() { + // `read_pos_` and `write_pos_` means the position of the reader and writer + // inside the buffer, respectively. When they're equal - its safe to reset + // them, because both reader and writer will continue doing their stuff + // from new (zero) positions. + if (read_head_->read_pos_ != read_head_->write_pos_) + return; + + // Reset positions + read_head_->read_pos_ = 0; + read_head_->write_pos_ = 0; + + // Move read_head_ forward, just in case if there're still some data to + // read in the next buffer. + if (read_head_ != write_head_) + read_head_ = read_head_->next_; +} + + size_t NodeBIO::Read(char* out, size_t size) { size_t bytes_read = 0; size_t expected = Length() > size ? size : Length(); @@ -213,16 +232,7 @@ size_t NodeBIO::Read(char* out, size_t size) { offset += avail; left -= avail; - // Move to next buffer - if (read_head_->read_pos_ == read_head_->write_pos_) { - read_head_->read_pos_ = 0; - read_head_->write_pos_ = 0; - - // But not get beyond write_head_ - if (length_ != bytes_read && read_head_ != write_head_) { - read_head_ = read_head_->next_; - } - } + TryMoveReadHead(); } assert(expected == bytes_read); length_ -= bytes_read; @@ -331,6 +341,10 @@ void NodeBIO::Write(const char* data, size_t size) { assert(write_head_->write_pos_ == kBufferLength); TryAllocateForWrite(); write_head_ = write_head_->next_; + + // Additionally, since we're moved to the next buffer, read head + // may be moved as well. + TryMoveReadHead(); } } assert(left == 0); diff --git a/src/node_crypto_bio.h b/src/node_crypto_bio.h index 865c7ca..615fea9 100644 --- a/src/node_crypto_bio.h +++ b/src/node_crypto_bio.h @@ -38,6 +38,9 @@ class NodeBIO { static BIO* New(); + // Move read head to next buffer if needed + void TryMoveReadHead(); + // Allocate new buffer for write if needed void TryAllocateForWrite(); -- 2.7.4