1 // Copyright Joyent, Inc. and other Node contributors.
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #include "node_crypto_bio.h"
23 #include "openssl/bio.h"
28 BIO_METHOD NodeBIO::method_ = {
42 int NodeBIO::New(BIO* bio) {
43 bio->ptr = new NodeBIO();
45 // XXX Why am I doing it?!
54 int NodeBIO::Free(BIO* bio) {
55 if (bio == NULL) return 0;
58 if (bio->init && bio->ptr != NULL) {
68 int NodeBIO::Read(BIO* bio, char* out, int len) {
70 BIO_clear_retry_flags(bio);
72 bytes = FromBIO(bio)->Read(out, len);
77 BIO_set_retry_read(bio);
85 int NodeBIO::Write(BIO* bio, const char* data, int len) {
86 BIO_clear_retry_flags(bio);
88 FromBIO(bio)->Write(data, len);
94 int NodeBIO::Puts(BIO* bio, const char* str) {
95 return Write(bio, str, strlen(str));
99 int NodeBIO::Gets(BIO* bio, char* out, int size) {
100 NodeBIO* nbio = FromBIO(bio);
102 if (nbio->Length() == 0)
105 int i = nbio->IndexOf('\n', size);
110 // Shift `i` a bit to NULL-terminate string later
122 long NodeBIO::Ctrl(BIO* bio, int cmd, long num, void* ptr) {
134 ret = nbio->Length() == 0;
136 case BIO_C_SET_BUF_MEM_EOF_RETURN:
140 ret = nbio->Length();
142 *reinterpret_cast<void**>(ptr) = NULL;
144 case BIO_C_SET_BUF_MEM:
145 assert(0 && "Can't use SET_BUF_MEM_PTR with NodeBIO");
148 case BIO_C_GET_BUF_MEM_PTR:
149 assert(0 && "Can't use GET_BUF_MEM_PTR with NodeBIO");
152 case BIO_CTRL_GET_CLOSE:
155 case BIO_CTRL_SET_CLOSE:
158 case BIO_CTRL_WPENDING:
161 case BIO_CTRL_PENDING:
162 ret = nbio->Length();
178 size_t NodeBIO::Read(char* out, size_t size) {
179 size_t bytes_read = 0;
180 size_t expected = Length() > size ? size : Length();
184 while (bytes_read < expected) {
185 assert(read_head_->read_pos_ <= read_head_->write_pos_);
186 size_t avail = read_head_->write_pos_ - read_head_->read_pos_;
192 memcpy(out + offset, read_head_->data_ + read_head_->read_pos_, avail);
193 read_head_->read_pos_ += avail;
200 // Move to next buffer
201 if (read_head_->read_pos_ == read_head_->write_pos_) {
202 read_head_->read_pos_ = 0;
203 read_head_->write_pos_ = 0;
205 // But not get beyond write_head_
206 if (bytes_read != expected)
207 read_head_ = read_head_->next_;
210 assert(expected == bytes_read);
211 length_ -= bytes_read;
217 size_t NodeBIO::IndexOf(char delim, size_t limit) {
218 size_t bytes_read = 0;
219 size_t max = Length() > limit ? limit : Length();
221 Buffer* current = read_head_;
223 while (bytes_read < max) {
224 assert(current->read_pos_ <= current->write_pos_);
225 size_t avail = current->write_pos_ - current->read_pos_;
230 char* tmp = current->data_ + current->read_pos_;
232 while (off < avail && *tmp != delim) {
246 // Move to next buffer
247 if (current->read_pos_ + avail == kBufferLength) {
248 current = current->next_;
251 assert(max == bytes_read);
257 void NodeBIO::Write(const char* data, size_t size) {
261 size_t to_write = left;
262 assert(write_head_->write_pos_ <= kBufferLength);
263 size_t avail = kBufferLength - write_head_->write_pos_;
265 if (to_write > avail)
269 memcpy(write_head_->data_ + write_head_->write_pos_,
277 write_head_->write_pos_ += to_write;
278 assert(write_head_->write_pos_ <= kBufferLength);
280 // Go to next buffer if there still are some bytes to write
282 if (write_head_->write_pos_ == kBufferLength) {
283 Buffer* next = new Buffer();
284 next->next_ = write_head_->next_;
285 write_head_->next_ = next;
287 write_head_ = write_head_->next_;
294 void NodeBIO::Reset() {
295 while (read_head_->read_pos_ != read_head_->write_pos_) {
296 assert(read_head_->write_pos_ > read_head_->read_pos_);
298 length_ -= read_head_->write_pos_ - read_head_->read_pos_;
299 read_head_->write_pos_ = 0;
300 read_head_->read_pos_ = 0;
302 read_head_ = read_head_->next_;
304 write_head_ = read_head_;
305 assert(length_ == 0);
309 NodeBIO::~NodeBIO() {
310 Buffer* current = head_.next_;
311 while (current != &head_) {
312 Buffer* next = current->next_;