📄 bss_bio.c
字号:
if (write_offset >= b->size) write_offset -= b->size; if (write_offset + num > b->size) /* no ring buffer wrap-around for non-copying interface * (to fulfil the promise by BIO_ctrl_get_write_guarantee, * BIO_nwrite may have to be called twice) */ num = b->size - write_offset; if (buf != NULL) *buf = b->buf + write_offset; assert(write_offset + num <= b->size); return num; }static ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) { struct bio_bio_st *b; ssize_t num, space; if (num_ > SSIZE_MAX) num = SSIZE_MAX; else num = (ssize_t)num_; space = bio_nwrite0(bio, buf); if (num > space) num = space; if (num <= 0) return num; b = bio->ptr; assert(b != NULL); b->len += num; assert(b->len <= b->size); return num; }static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { long ret; struct bio_bio_st *b = bio->ptr; assert(b != NULL); switch (cmd) { /* specific CTRL codes */ case BIO_C_SET_WRITE_BUF_SIZE: if (b->peer) { BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); ret = 0; } else if (num == 0) { BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); ret = 0; } else { size_t new_size = num; if (b->size != new_size) { if (b->buf) { OPENSSL_free(b->buf); b->buf = NULL; } b->size = new_size; } ret = 1; } break; case BIO_C_GET_WRITE_BUF_SIZE: ret = (long) b->size; break; case BIO_C_MAKE_BIO_PAIR: { BIO *other_bio = ptr; if (bio_make_pair(bio, other_bio)) ret = 1; else ret = 0; } break; case BIO_C_DESTROY_BIO_PAIR: /* Affects both BIOs in the pair -- call just once! * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ bio_destroy_pair(bio); ret = 1; break; case BIO_C_GET_WRITE_GUARANTEE: /* How many bytes can the caller feed to the next write * without having to keep any? */ if (b->peer == NULL || b->closed) ret = 0; else ret = (long) b->size - b->len; break; case BIO_C_GET_READ_REQUEST: /* If the peer unsuccessfully tried to read, how many bytes * were requested? (As with BIO_CTRL_PENDING, that number * can usually be treated as boolean.) */ ret = (long) b->request; break; case BIO_C_RESET_READ_REQUEST: /* Reset request. (Can be useful after read attempts * at the other side that are meant to be non-blocking, * e.g. when probing SSL_read to see if any data is * available.) */ b->request = 0; ret = 1; break; case BIO_C_SHUTDOWN_WR: /* similar to shutdown(..., SHUT_WR) */ b->closed = 1; ret = 1; break; case BIO_C_NREAD0: /* prepare for non-copying read */ ret = (long) bio_nread0(bio, ptr); break; case BIO_C_NREAD: /* non-copying read */ ret = (long) bio_nread(bio, ptr, (size_t) num); break; case BIO_C_NWRITE0: /* prepare for non-copying write */ ret = (long) bio_nwrite0(bio, ptr); break; case BIO_C_NWRITE: /* non-copying write */ ret = (long) bio_nwrite(bio, ptr, (size_t) num); break; /* standard CTRL codes follow */ case BIO_CTRL_RESET: if (b->buf != NULL) { b->len = 0; b->offset = 0; } ret = 0; break; case BIO_CTRL_GET_CLOSE: ret = bio->shutdown; break; case BIO_CTRL_SET_CLOSE: bio->shutdown = (int) num; ret = 1; break; case BIO_CTRL_PENDING: if (b->peer != NULL) { struct bio_bio_st *peer_b = b->peer->ptr; ret = (long) peer_b->len; } else ret = 0; break; case BIO_CTRL_WPENDING: if (b->buf != NULL) ret = (long) b->len; else ret = 0; break; case BIO_CTRL_DUP: /* See BIO_dup_chain for circumstances we have to expect. */ { BIO *other_bio = ptr; struct bio_bio_st *other_b; assert(other_bio != NULL); other_b = other_bio->ptr; assert(other_b != NULL); assert(other_b->buf == NULL); /* other_bio is always fresh */ other_b->size = b->size; } ret = 1; break; case BIO_CTRL_FLUSH: ret = 1; break; case BIO_CTRL_EOF: { BIO *other_bio = ptr; if (other_bio) { struct bio_bio_st *other_b = other_bio->ptr; assert(other_b != NULL); ret = other_b->len == 0 && other_b->closed; } else ret = 1; } break; default: ret = 0; } return ret; }static int bio_puts(BIO *bio, const char *str) { return bio_write(bio, str, strlen(str)); }static int bio_make_pair(BIO *bio1, BIO *bio2) { struct bio_bio_st *b1, *b2; assert(bio1 != NULL); assert(bio2 != NULL); b1 = bio1->ptr; b2 = bio2->ptr; if (b1->peer != NULL || b2->peer != NULL) { BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); return 0; } if (b1->buf == NULL) { b1->buf = OPENSSL_malloc(b1->size); if (b1->buf == NULL) { BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); return 0; } b1->len = 0; b1->offset = 0; } if (b2->buf == NULL) { b2->buf = OPENSSL_malloc(b2->size); if (b2->buf == NULL) { BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); return 0; } b2->len = 0; b2->offset = 0; } b1->peer = bio2; b1->closed = 0; b1->request = 0; b2->peer = bio1; b2->closed = 0; b2->request = 0; bio1->init = 1; bio2->init = 1; return 1; }static void bio_destroy_pair(BIO *bio) { struct bio_bio_st *b = bio->ptr; if (b != NULL) { BIO *peer_bio = b->peer; if (peer_bio != NULL) { struct bio_bio_st *peer_b = peer_bio->ptr; assert(peer_b != NULL); assert(peer_b->peer == bio); peer_b->peer = NULL; peer_bio->init = 0; assert(peer_b->buf != NULL); peer_b->len = 0; peer_b->offset = 0; b->peer = NULL; bio->init = 0; assert(b->buf != NULL); b->len = 0; b->offset = 0; } } } /* Exported convenience functions */int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p, size_t writebuf2) { BIO *bio1 = NULL, *bio2 = NULL; long r; int ret = 0; bio1 = BIO_new(BIO_s_bio()); if (bio1 == NULL) goto err; bio2 = BIO_new(BIO_s_bio()); if (bio2 == NULL) goto err; if (writebuf1) { r = BIO_set_write_buf_size(bio1, writebuf1); if (!r) goto err; } if (writebuf2) { r = BIO_set_write_buf_size(bio2, writebuf2); if (!r) goto err; } r = BIO_make_bio_pair(bio1, bio2); if (!r) goto err; ret = 1; err: if (ret == 0) { if (bio1) { BIO_free(bio1); bio1 = NULL; } if (bio2) { BIO_free(bio2); bio2 = NULL; } } *bio1_p = bio1; *bio2_p = bio2; return ret; }size_t BIO_ctrl_get_write_guarantee(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); }size_t BIO_ctrl_get_read_request(BIO *bio) { return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); }int BIO_ctrl_reset_read_request(BIO *bio) { return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); }/* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now * (conceivably some other BIOs could allow non-copying reads and writes too.) */int BIO_nread0(BIO *bio, char **buf) { long ret; if (!bio->init) { BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); return -2; } ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); if (ret > INT_MAX) return INT_MAX; else return (int) ret; }int BIO_nread(BIO *bio, char **buf, int num) { int ret; if (!bio->init) { BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); return -2; } ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); if (ret > 0) bio->num_read += ret; return ret; }int BIO_nwrite0(BIO *bio, char **buf) { long ret; if (!bio->init) { BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); return -2; } ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); if (ret > INT_MAX) return INT_MAX; else return (int) ret; }int BIO_nwrite(BIO *bio, char **buf, int num) { int ret; if (!bio->init) { BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); return -2; } ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); if (ret > 0) bio->num_write += ret; return ret; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -