Beispiel #1
0
int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
  struct bio_bio_st* b;
  struct bio_bio_st* peer_b;
  size_t max_available;
  size_t dummy_read_offset;
  uint8_t* dummy_read_buf;

  assert(BIO_get_retry_flags(bio) == 0);

  if (!bio->init) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
    return 0;
  }

  b = bio->ptr;

  if (!b || !b->peer) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
    return 0;
  }

  peer_b = b->peer->ptr;
  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
    return 0;
  }

  if (!peer_b->zero_copy_read_lock) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
    return 0;
  }

  max_available =
      bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
  if (bytes_read > max_available) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
    return 0;
  }

  peer_b->len -= bytes_read;
  assert(peer_b->len >= 0);
  assert(peer_b->offset + bytes_read <= peer_b->size);

  /* Move read offset. If zero_copy_write_lock == 1 we must advance the
   * offset even if buffer becomes empty, to make sure
   * write_offset = (offset + len) mod size does not change. */
  if (peer_b->offset + bytes_read == peer_b->size ||
      (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
    peer_b->offset = 0;
  } else {
    peer_b->offset += bytes_read;
  }

  bio->num_read += bytes_read;
  peer_b->zero_copy_read_lock = 0;
  return 1;
}
Beispiel #2
0
int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
                               size_t* out_buf_offset,
                               size_t* out_available_bytes) {
    struct bio_bio_st* b;
    struct bio_bio_st* peer_b;
    size_t max_available;
    *out_available_bytes = 0;

    BIO_clear_retry_flags(bio);

    if (!bio->init) {
        OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_UNINITIALIZED);
        return 0;
    }

    b = bio->ptr;

    if (!b || !b->peer) {
        OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
                          BIO_R_UNSUPPORTED_METHOD);
        return 0;
    }

    peer_b = b->peer->ptr;
    if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
        OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf,
                          BIO_R_UNSUPPORTED_METHOD);
        return 0;
    }

    if (peer_b->zero_copy_read_lock) {
        OPENSSL_PUT_ERROR(BIO, BIO_zero_copy_get_read_buf, BIO_R_INVALID_ARGUMENT);
        return 0;
    }

    peer_b->request = 0;  /* Is not used by zero-copy API. */

    max_available =
        bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);

    assert(peer_b->buf != NULL);
    if (max_available > 0) {
        peer_b->zero_copy_read_lock = 1;
    }

    *out_available_bytes = max_available;
    return 1;
}