Home | History | Annotate | Download | only in bio
      1 /* ====================================================================
      2  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in
     13  *    the documentation and/or other materials provided with the
     14  *    distribution.
     15  *
     16  * 3. All advertising materials mentioning features or use of this
     17  *    software must display the following acknowledgment:
     18  *    "This product includes software developed by the OpenSSL Project
     19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
     20  *
     21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     22  *    endorse or promote products derived from this software without
     23  *    prior written permission. For written permission, please contact
     24  *    openssl-core (at) openssl.org.
     25  *
     26  * 5. Products derived from this software may not be called "OpenSSL"
     27  *    nor may "OpenSSL" appear in their names without prior written
     28  *    permission of the OpenSSL Project.
     29  *
     30  * 6. Redistributions of any form whatsoever must retain the following
     31  *    acknowledgment:
     32  *    "This product includes software developed by the OpenSSL Project
     33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
     34  *
     35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     46  * OF THE POSSIBILITY OF SUCH DAMAGE.
     47  * ====================================================================
     48  *
     49  * This product includes cryptographic software written by Eric Young
     50  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     51  * Hudson (tjh (at) cryptsoft.com). */
     52 
     53 #include <openssl/bio.h>
     54 
     55 #include <assert.h>
     56 #include <string.h>
     57 
     58 #include <openssl/buf.h>
     59 #include <openssl/err.h>
     60 #include <openssl/mem.h>
     61 
     62 
     63 struct bio_bio_st {
     64   BIO *peer; /* NULL if buf == NULL.
     65               * If peer != NULL, then peer->ptr is also a bio_bio_st,
     66               * and its "peer" member points back to us.
     67               * peer != NULL iff init != 0 in the BIO. */
     68 
     69   /* This is for what we write (i.e. reading uses peer's struct): */
     70   int closed;    /* valid iff peer != NULL */
     71   size_t len;    /* valid iff buf != NULL; 0 if peer == NULL */
     72   size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
     73   size_t size;
     74   uint8_t *buf; /* "size" elements (if != NULL) */
     75   char buf_externally_allocated; /* true iff buf was externally allocated. */
     76 
     77   char zero_copy_read_lock;  /* true iff a zero copy read operation
     78                               * is in progress. */
     79   char zero_copy_write_lock; /* true iff a zero copy write operation
     80                               * is in progress. */
     81 
     82   size_t request; /* valid iff peer != NULL; 0 if len != 0,
     83                    * otherwise set by peer to number of bytes
     84                    * it (unsuccessfully) tried to read,
     85                    * never more than buffer space (size-len) warrants. */
     86 };
     87 
     88 static int bio_new(BIO *bio) {
     89   struct bio_bio_st *b;
     90 
     91   b = OPENSSL_malloc(sizeof *b);
     92   if (b == NULL) {
     93     return 0;
     94   }
     95   memset(b, 0, sizeof(struct bio_bio_st));
     96 
     97   b->size = 17 * 1024; /* enough for one TLS record (just a default) */
     98   bio->ptr = b;
     99   return 1;
    100 }
    101 
    102 static void bio_destroy_pair(BIO *bio) {
    103   struct bio_bio_st *b = bio->ptr;
    104   BIO *peer_bio;
    105   struct bio_bio_st *peer_b;
    106 
    107   if (b == NULL) {
    108     return;
    109   }
    110 
    111   peer_bio = b->peer;
    112   if (peer_bio == NULL) {
    113     return;
    114   }
    115 
    116   peer_b = peer_bio->ptr;
    117 
    118   assert(peer_b != NULL);
    119   assert(peer_b->peer == bio);
    120 
    121   peer_b->peer = NULL;
    122   peer_bio->init = 0;
    123   assert(peer_b->buf != NULL);
    124   peer_b->len = 0;
    125   peer_b->offset = 0;
    126 
    127   b->peer = NULL;
    128   bio->init = 0;
    129   assert(b->buf != NULL);
    130   b->len = 0;
    131   b->offset = 0;
    132 }
    133 
    134 static int bio_free(BIO *bio) {
    135   struct bio_bio_st *b;
    136 
    137   if (bio == NULL) {
    138     return 0;
    139   }
    140   b = bio->ptr;
    141 
    142   assert(b != NULL);
    143 
    144   if (b->peer) {
    145     bio_destroy_pair(bio);
    146   }
    147 
    148   if (!b->buf_externally_allocated) {
    149     OPENSSL_free(b->buf);
    150   }
    151 
    152   OPENSSL_free(b);
    153 
    154   return 1;
    155 }
    156 
    157 static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
    158                                          uint8_t** out_read_buf,
    159                                          size_t* out_buf_offset) {
    160   size_t max_available;
    161   if (peer_b->len > peer_b->size - peer_b->offset) {
    162     /* Only the first half of the ring buffer can be read. */
    163     max_available = peer_b->size - peer_b->offset;
    164   } else {
    165     max_available = peer_b->len;
    166   }
    167 
    168   *out_read_buf = peer_b->buf;
    169   *out_buf_offset = peer_b->offset;
    170   return max_available;
    171 }
    172 
    173 int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
    174                                size_t* out_buf_offset,
    175                                size_t* out_available_bytes) {
    176   struct bio_bio_st* b;
    177   struct bio_bio_st* peer_b;
    178   size_t max_available;
    179   *out_available_bytes = 0;
    180 
    181   BIO_clear_retry_flags(bio);
    182 
    183   if (!bio->init) {
    184     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_UNINITIALIZED);
    185     return 0;
    186   }
    187 
    188   b = bio->ptr;
    189 
    190   if (!b || !b->peer) {
    191     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
    192                       BIO_R_UNSUPPORTED_METHOD);
    193     return 0;
    194   }
    195 
    196   peer_b = b->peer->ptr;
    197   if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
    198     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
    199                       BIO_R_UNSUPPORTED_METHOD);
    200     return 0;
    201   }
    202 
    203   if (peer_b->zero_copy_read_lock) {
    204     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_INVALID_ARGUMENT);
    205     return 0;
    206   }
    207 
    208   peer_b->request = 0;  /* Is not used by zero-copy API. */
    209 
    210   max_available =
    211       bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
    212 
    213   assert(peer_b->buf != NULL);
    214   if (max_available > 0) {
    215     peer_b->zero_copy_read_lock = 1;
    216   }
    217 
    218   *out_available_bytes = max_available;
    219   return 1;
    220 }
    221 
    222 int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
    223   struct bio_bio_st* b;
    224   struct bio_bio_st* peer_b;
    225   size_t max_available;
    226   size_t dummy_read_offset;
    227   uint8_t* dummy_read_buf;
    228 
    229   assert(BIO_get_retry_flags(bio) == 0);
    230 
    231   if (!bio->init) {
    232     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
    233                       BIO_R_UNINITIALIZED);
    234     return 0;
    235   }
    236 
    237   b = bio->ptr;
    238 
    239   if (!b || !b->peer) {
    240     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
    241                       BIO_R_UNSUPPORTED_METHOD);
    242     return 0;
    243   }
    244 
    245   peer_b = b->peer->ptr;
    246   if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
    247     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
    248                       BIO_R_UNSUPPORTED_METHOD);
    249     return 0;
    250   }
    251 
    252   if (!peer_b->zero_copy_read_lock) {
    253     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
    254                       BIO_R_INVALID_ARGUMENT);
    255     return 0;
    256   }
    257 
    258   max_available =
    259       bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
    260   if (bytes_read > max_available) {
    261     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf_done,
    262                       BIO_R_INVALID_ARGUMENT);
    263     return 0;
    264   }
    265 
    266   peer_b->len -= bytes_read;
    267   assert(peer_b->len >= 0);
    268   assert(peer_b->offset + bytes_read <= peer_b->size);
    269 
    270   /* Move read offset. If zero_copy_write_lock == 1 we must advance the
    271    * offset even if buffer becomes empty, to make sure
    272    * write_offset = (offset + len) mod size does not change. */
    273   if (peer_b->offset + bytes_read == peer_b->size ||
    274       (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
    275     peer_b->offset = 0;
    276   } else {
    277     peer_b->offset += bytes_read;
    278   }
    279 
    280   bio->num_read += bytes_read;
    281   peer_b->zero_copy_read_lock = 0;
    282   return 1;
    283 }
    284 
    285 static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
    286                                           uint8_t** out_write_buf,
    287                                           size_t* out_buf_offset) {
    288   size_t write_offset;
    289   size_t max_available;
    290 
    291   assert(b->len <= b->size);
    292 
    293   write_offset = b->offset + b->len;
    294 
    295   if (write_offset >= b->size) {
    296     /* Only the first half of the ring buffer can be written to. */
    297     write_offset -= b->size;
    298     /* write up to the start of the ring buffer. */
    299     max_available = b->offset - write_offset;
    300   } else {
    301     /* write up to the end the buffer. */
    302     max_available = b->size - write_offset;
    303   }
    304 
    305   *out_write_buf = b->buf;
    306   *out_buf_offset = write_offset;
    307   return max_available;
    308 }
    309 
    310 int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
    311                                 size_t* out_buf_offset,
    312                                 size_t* out_available_bytes) {
    313   struct bio_bio_st* b;
    314   struct bio_bio_st* peer_b;
    315   size_t max_available;
    316 
    317   *out_available_bytes = 0;
    318   BIO_clear_retry_flags(bio);
    319 
    320   if (!bio->init) {
    321     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_UNINITIALIZED);
    322     return 0;
    323   }
    324 
    325   b = bio->ptr;
    326 
    327   if (!b || !b->buf || !b->peer) {
    328     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf,
    329                       BIO_R_UNSUPPORTED_METHOD);
    330     return 0;
    331   }
    332   peer_b = b->peer->ptr;
    333   if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
    334     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf,
    335                       BIO_R_UNSUPPORTED_METHOD);
    336     return 0;
    337   }
    338 
    339   assert(b->buf != NULL);
    340 
    341   if (b->zero_copy_write_lock) {
    342     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_INVALID_ARGUMENT);
    343     return 0;
    344   }
    345 
    346   b->request = 0;
    347   if (b->closed) {
    348     /* Bio is already closed. */
    349     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf, BIO_R_BROKEN_PIPE);
    350     return 0;
    351   }
    352 
    353   max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
    354 
    355   if (max_available > 0) {
    356     b->zero_copy_write_lock = 1;
    357   }
    358 
    359   *out_available_bytes = max_available;
    360   return 1;
    361 }
    362 
    363 int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
    364   struct bio_bio_st* b;
    365   struct bio_bio_st* peer_b;
    366 
    367   size_t rest;
    368   size_t dummy_write_offset;
    369   uint8_t* dummy_write_buf;
    370 
    371   if (!bio->init) {
    372     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
    373                       BIO_R_UNINITIALIZED);
    374     return 0;
    375   }
    376 
    377   b = bio->ptr;
    378 
    379   if (!b || !b->buf || !b->peer) {
    380     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
    381                       BIO_R_UNSUPPORTED_METHOD);
    382     return 0;
    383   }
    384   peer_b = b->peer->ptr;
    385   if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
    386     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
    387                       BIO_R_UNSUPPORTED_METHOD);
    388     return 0;
    389   }
    390 
    391   b->request = 0;
    392   if (b->closed) {
    393     /* BIO is already closed. */
    394     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done, BIO_R_BROKEN_PIPE);
    395     return 0;
    396   }
    397 
    398   if (!b->zero_copy_write_lock) {
    399     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
    400                       BIO_R_INVALID_ARGUMENT);
    401     return 0;
    402   }
    403 
    404   rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
    405 
    406   if (bytes_written > rest) {
    407     OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_write_buf_done,
    408                       BIO_R_INVALID_ARGUMENT);
    409     return 0;
    410   }
    411 
    412   bio->num_write += bytes_written;
    413   /* Move write offset. */
    414   b->len += bytes_written;
    415   b->zero_copy_write_lock = 0;
    416   return 1;
    417 }
    418 
    419 static int bio_read(BIO *bio, char *buf, int size_) {
    420   size_t size = size_;
    421   size_t rest;
    422   struct bio_bio_st *b, *peer_b;
    423 
    424   BIO_clear_retry_flags(bio);
    425 
    426   if (!bio->init) {
    427     return 0;
    428   }
    429 
    430   b = bio->ptr;
    431   assert(b != NULL);
    432   assert(b->peer != NULL);
    433   peer_b = b->peer->ptr;
    434   assert(peer_b != NULL);
    435   assert(peer_b->buf != NULL);
    436 
    437   peer_b->request = 0; /* will be set in "retry_read" situation */
    438 
    439   if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
    440     return 0;
    441   }
    442 
    443   if (peer_b->len == 0) {
    444     if (peer_b->closed) {
    445       return 0; /* writer has closed, and no data is left */
    446     } else {
    447       BIO_set_retry_read(bio); /* buffer is empty */
    448       if (size <= peer_b->size) {
    449         peer_b->request = size;
    450       } else {
    451         /* don't ask for more than the peer can
    452          * deliver in one write */
    453         peer_b->request = peer_b->size;
    454       }
    455       return -1;
    456     }
    457   }
    458 
    459   /* we can read */
    460   if (peer_b->len < size) {
    461     size = peer_b->len;
    462   }
    463 
    464   /* now read "size" bytes */
    465   rest = size;
    466 
    467   assert(rest > 0);
    468   /* one or two iterations */
    469   do {
    470     size_t chunk;
    471 
    472     assert(rest <= peer_b->len);
    473     if (peer_b->offset + rest <= peer_b->size) {
    474       chunk = rest;
    475     } else {
    476       /* wrap around ring buffer */
    477       chunk = peer_b->size - peer_b->offset;
    478     }
    479     assert(peer_b->offset + chunk <= peer_b->size);
    480 
    481     memcpy(buf, peer_b->buf + peer_b->offset, chunk);
    482 
    483     peer_b->len -= chunk;
    484     /* If zero_copy_write_lock == 1 we must advance the offset even if buffer
    485      * becomes empty, to make sure write_offset = (offset + len) % size
    486      * does not change. */
    487     if (peer_b->len || peer_b->zero_copy_write_lock) {
    488       peer_b->offset += chunk;
    489       assert(peer_b->offset <= peer_b->size);
    490       if (peer_b->offset == peer_b->size) {
    491         peer_b->offset = 0;
    492       }
    493       buf += chunk;
    494     } else {
    495       /* buffer now empty, no need to advance "buf" */
    496       assert(chunk == rest);
    497       peer_b->offset = 0;
    498     }
    499     rest -= chunk;
    500   } while (rest);
    501 
    502   return size;
    503 }
    504 
    505 static int bio_write(BIO *bio, const char *buf, int num_) {
    506   size_t num = num_;
    507   size_t rest;
    508   struct bio_bio_st *b;
    509 
    510   BIO_clear_retry_flags(bio);
    511 
    512   if (!bio->init || buf == NULL || num == 0) {
    513     return 0;
    514   }
    515 
    516   b = bio->ptr;
    517   assert(b != NULL);
    518   assert(b->peer != NULL);
    519   assert(b->buf != NULL);
    520 
    521   if (b->zero_copy_write_lock) {
    522     return 0;
    523   }
    524 
    525   b->request = 0;
    526   if (b->closed) {
    527     /* we already closed */
    528     OPENSSL_PUT_ERROR(BIO, bio_write, BIO_R_BROKEN_PIPE);
    529     return -1;
    530   }
    531 
    532   assert(b->len <= b->size);
    533 
    534   if (b->len == b->size) {
    535     BIO_set_retry_write(bio); /* buffer is full */
    536     return -1;
    537   }
    538 
    539   /* we can write */
    540   if (num > b->size - b->len) {
    541     num = b->size - b->len;
    542   }
    543 
    544   /* now write "num" bytes */
    545   rest = num;
    546 
    547   assert(rest > 0);
    548   /* one or two iterations */
    549   do {
    550     size_t write_offset;
    551     size_t chunk;
    552 
    553     assert(b->len + rest <= b->size);
    554 
    555     write_offset = b->offset + b->len;
    556     if (write_offset >= b->size) {
    557       write_offset -= b->size;
    558     }
    559     /* b->buf[write_offset] is the first byte we can write to. */
    560 
    561     if (write_offset + rest <= b->size) {
    562       chunk = rest;
    563     } else {
    564       /* wrap around ring buffer */
    565       chunk = b->size - write_offset;
    566     }
    567 
    568     memcpy(b->buf + write_offset, buf, chunk);
    569 
    570     b->len += chunk;
    571 
    572     assert(b->len <= b->size);
    573 
    574     rest -= chunk;
    575     buf += chunk;
    576   } while (rest);
    577 
    578   return num;
    579 }
    580 
    581 static int bio_make_pair(BIO* bio1, BIO* bio2,
    582                          size_t writebuf1_len, uint8_t* ext_writebuf1,
    583                          size_t writebuf2_len, uint8_t* ext_writebuf2) {
    584   struct bio_bio_st *b1, *b2;
    585 
    586   assert(bio1 != NULL);
    587   assert(bio2 != NULL);
    588 
    589   b1 = bio1->ptr;
    590   b2 = bio2->ptr;
    591 
    592   if (b1->peer != NULL || b2->peer != NULL) {
    593     OPENSSL_PUT_ERROR(BIO, bio_make_pair, BIO_R_IN_USE);
    594     return 0;
    595   }
    596 
    597   assert(b1->buf_externally_allocated == 0);
    598   assert(b2->buf_externally_allocated == 0);
    599 
    600   if (b1->buf == NULL) {
    601     if (writebuf1_len) {
    602       b1->size = writebuf1_len;
    603     }
    604     if (!ext_writebuf1) {
    605       b1->buf_externally_allocated = 0;
    606       b1->buf = OPENSSL_malloc(b1->size);
    607       if (b1->buf == NULL) {
    608         OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
    609         return 0;
    610       }
    611     } else {
    612       b1->buf = ext_writebuf1;
    613       b1->buf_externally_allocated = 1;
    614     }
    615     b1->len = 0;
    616     b1->offset = 0;
    617   }
    618 
    619   if (b2->buf == NULL) {
    620     if (writebuf2_len) {
    621       b2->size = writebuf2_len;
    622     }
    623     if (!ext_writebuf2) {
    624       b2->buf_externally_allocated = 0;
    625       b2->buf = OPENSSL_malloc(b2->size);
    626       if (b2->buf == NULL) {
    627         OPENSSL_PUT_ERROR(BIO, bio_make_pair, ERR_R_MALLOC_FAILURE);
    628         return 0;
    629       }
    630     } else {
    631       b2->buf = ext_writebuf2;
    632       b2->buf_externally_allocated = 1;
    633     }
    634     b2->len = 0;
    635     b2->offset = 0;
    636   }
    637 
    638   b1->peer = bio2;
    639   b1->closed = 0;
    640   b1->request = 0;
    641   b1->zero_copy_read_lock = 0;
    642   b1->zero_copy_write_lock = 0;
    643   b2->peer = bio1;
    644   b2->closed = 0;
    645   b2->request = 0;
    646   b2->zero_copy_read_lock = 0;
    647   b2->zero_copy_write_lock = 0;
    648 
    649   bio1->init = 1;
    650   bio2->init = 1;
    651 
    652   return 1;
    653 }
    654 
    655 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
    656   long ret;
    657   struct bio_bio_st *b = bio->ptr;
    658 
    659   assert(b != NULL);
    660 
    661   switch (cmd) {
    662     /* specific CTRL codes */
    663 
    664     case BIO_C_GET_WRITE_BUF_SIZE:
    665       ret = (long)b->size;
    666       break;
    667 
    668     case BIO_C_GET_WRITE_GUARANTEE:
    669       /* How many bytes can the caller feed to the next write
    670        * without having to keep any? */
    671       if (b->peer == NULL || b->closed) {
    672         ret = 0;
    673       } else {
    674         ret = (long)b->size - b->len;
    675       }
    676       break;
    677 
    678     case BIO_C_GET_READ_REQUEST:
    679       /* If the peer unsuccessfully tried to read, how many bytes
    680        * were requested?  (As with BIO_CTRL_PENDING, that number
    681        * can usually be treated as boolean.) */
    682       ret = (long)b->request;
    683       break;
    684 
    685     case BIO_C_RESET_READ_REQUEST:
    686       /* Reset request.  (Can be useful after read attempts
    687        * at the other side that are meant to be non-blocking,
    688        * e.g. when probing SSL_read to see if any data is
    689        * available.) */
    690       b->request = 0;
    691       ret = 1;
    692       break;
    693 
    694     case BIO_C_SHUTDOWN_WR:
    695       /* similar to shutdown(..., SHUT_WR) */
    696       b->closed = 1;
    697       ret = 1;
    698       break;
    699 
    700     /* standard CTRL codes follow */
    701 
    702     case BIO_CTRL_GET_CLOSE:
    703       ret = bio->shutdown;
    704       break;
    705 
    706     case BIO_CTRL_SET_CLOSE:
    707       bio->shutdown = (int)num;
    708       ret = 1;
    709       break;
    710 
    711     case BIO_CTRL_PENDING:
    712       if (b->peer != NULL) {
    713         struct bio_bio_st *peer_b = b->peer->ptr;
    714         ret = (long)peer_b->len;
    715       } else {
    716         ret = 0;
    717       }
    718       break;
    719 
    720     case BIO_CTRL_WPENDING:
    721       ret = 0;
    722       if (b->buf != NULL) {
    723         ret = (long)b->len;
    724       }
    725       break;
    726 
    727     case BIO_CTRL_FLUSH:
    728       ret = 1;
    729       break;
    730 
    731     case BIO_CTRL_EOF: {
    732       BIO *other_bio = ptr;
    733 
    734       if (other_bio) {
    735         struct bio_bio_st *other_b = other_bio->ptr;
    736         assert(other_b != NULL);
    737         ret = other_b->len == 0 && other_b->closed;
    738       } else {
    739         ret = 1;
    740       }
    741     } break;
    742 
    743     default:
    744       ret = 0;
    745   }
    746   return ret;
    747 }
    748 
    749 static int bio_puts(BIO *bio, const char *str) {
    750   return bio_write(bio, str, strlen(str));
    751 }
    752 
    753 static const BIO_METHOD methods_biop = {
    754     BIO_TYPE_BIO, "BIO pair",             bio_write, bio_read,
    755     bio_puts,     NULL /* no bio_gets */, bio_ctrl,  bio_new,
    756     bio_free,     NULL /* no bio_callback_ctrl */
    757 };
    758 
    759 const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
    760 
    761 int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
    762                      BIO** bio2_p, size_t writebuf2) {
    763   return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
    764                                        writebuf2, NULL);
    765 }
    766 
    767 int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
    768                                   uint8_t* ext_writebuf1,
    769                                   BIO** bio2_p, size_t writebuf2_len,
    770                                   uint8_t* ext_writebuf2) {
    771   BIO *bio1 = NULL, *bio2 = NULL;
    772   int ret = 0;
    773 
    774   /* External buffers must have sizes greater than 0. */
    775   if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
    776     goto err;
    777   }
    778 
    779   bio1 = BIO_new(bio_s_bio());
    780   if (bio1 == NULL) {
    781     goto err;
    782   }
    783   bio2 = BIO_new(bio_s_bio());
    784   if (bio2 == NULL) {
    785     goto err;
    786   }
    787 
    788   if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
    789                      ext_writebuf2)) {
    790     goto err;
    791   }
    792   ret = 1;
    793 
    794 err:
    795   if (ret == 0) {
    796     BIO_free(bio1);
    797     bio1 = NULL;
    798     BIO_free(bio2);
    799     bio2 = NULL;
    800   }
    801 
    802   *bio1_p = bio1;
    803   *bio2_p = bio2;
    804   return ret;
    805 }
    806 
    807 size_t BIO_ctrl_get_read_request(BIO *bio) {
    808   return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
    809 }
    810 
    811 size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
    812   return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
    813 }
    814 
    815 int BIO_shutdown_wr(BIO *bio) {
    816   return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
    817 }
    818