int MaOpenSslSocket::initConnection() { BIO *bioSSL, *bioSock; if (bio) { return 0; } bio = BIO_new(BIO_f_buffer()); if (bio == 0) { return MPR_ERR_CANT_INITIALIZE; } BIO_set_write_buffer_size(bio, 128); ssl = (SSL*) SSL_new(context); mprAssert(ssl); if (ssl == 0) { return MPR_ERR_CANT_INITIALIZE; } SSL_set_app_data(ssl, (void*) this); SSL_set_session(ssl, 0); bioSSL = BIO_new(BIO_f_ssl()); mprAssert(bioSSL); bioSock = BIO_new_socket(sock, BIO_NOCLOSE); mprAssert(bioSock); SSL_set_bio(ssl, bioSock, bioSock); SSL_set_accept_state(ssl); BIO_set_ssl(bioSSL, ssl, BIO_CLOSE); BIO_push(bio, bioSSL); return 0; }
static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; BIO_LINEBUFFER_CTX *ctx; long ret = 1; char *p; int r; int obs; ctx = (BIO_LINEBUFFER_CTX *)b->ptr; switch (cmd) { case BIO_CTRL_RESET: ctx->obuf_len = 0; if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; case BIO_CTRL_INFO: ret = (long)ctx->obuf_len; break; case BIO_CTRL_WPENDING: ret = (long)ctx->obuf_len; if (ret == 0) { if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); } break; case BIO_C_SET_BUFF_SIZE: obs = (int)num; p = ctx->obuf; if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) { p = (char *)OPENSSL_malloc((int)num); if (p == NULL) goto malloc_error; } if (ctx->obuf != p) { if (ctx->obuf_len > obs) { ctx->obuf_len = obs; } memcpy(p, ctx->obuf, ctx->obuf_len); OPENSSL_free(ctx->obuf); ctx->obuf = p; ctx->obuf_size = obs; } break; case BIO_C_DO_STATE_MACHINE: if (b->next_bio == NULL) return (0); BIO_clear_retry_flags(b); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); BIO_copy_next_retry(b); break; case BIO_CTRL_FLUSH: if (b->next_bio == NULL) return (0); if (ctx->obuf_len <= 0) { ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; } for (;;) { BIO_clear_retry_flags(b); if (ctx->obuf_len > 0) { r = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); #if 0 fprintf(stderr, "FLUSH %3d -> %3d\n", ctx->obuf_len, r); #endif BIO_copy_next_retry(b); if (r <= 0) return ((long)r); if (r < ctx->obuf_len) memmove(ctx->obuf, ctx->obuf + r, ctx->obuf_len - r); ctx->obuf_len -= r; } else { ctx->obuf_len = 0; ret = 1; break; } } ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; if (!BIO_set_write_buffer_size(dbio, ctx->obuf_size)) ret = 0; break; default: if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; } return (ret); malloc_error: BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE); return (0); }
static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO *dbio; BIO_F_BUFFER_CTX *ctx; long ret = 1; char *p1, *p2; int r, i, *ip; int ibs, obs; ctx = (BIO_F_BUFFER_CTX *)b->ptr; switch (cmd) { case BIO_CTRL_RESET: ctx->ibuf_off = 0; ctx->ibuf_len = 0; ctx->obuf_off = 0; ctx->obuf_len = 0; if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; case BIO_CTRL_INFO: ret = (long)ctx->obuf_len; break; case BIO_C_GET_BUFF_NUM_LINES: ret = 0; p1 = ctx->ibuf; for (i = 0; i < ctx->ibuf_len; i++) { if (p1[ctx->ibuf_off + i] == '\n') ret++; } break; case BIO_CTRL_WPENDING: ret = (long)ctx->obuf_len; if (ret == 0) { if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); } break; case BIO_CTRL_PENDING: ret = (long)ctx->ibuf_len; if (ret == 0) { if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); } break; case BIO_C_SET_BUFF_READ_DATA: if (num > ctx->ibuf_size) { p1 = malloc(num); if (p1 == NULL) goto malloc_error; free(ctx->ibuf); ctx->ibuf = p1; } ctx->ibuf_off = 0; ctx->ibuf_len = (int)num; memcpy(ctx->ibuf, ptr, num); ret = 1; break; case BIO_C_SET_BUFF_SIZE: if (ptr != NULL) { ip = (int *)ptr; if (*ip == 0) { ibs = (int)num; obs = ctx->obuf_size; } else /* if (*ip == 1) */ { ibs = ctx->ibuf_size; obs = (int)num; } } else { ibs = (int)num; obs = (int)num; } p1 = ctx->ibuf; p2 = ctx->obuf; if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) { p1 = malloc(num); if (p1 == NULL) goto malloc_error; } if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { p2 = malloc(num); if (p2 == NULL) { if (p1 != ctx->ibuf) free(p1); goto malloc_error; } } if (ctx->ibuf != p1) { free(ctx->ibuf); ctx->ibuf = p1; ctx->ibuf_off = 0; ctx->ibuf_len = 0; ctx->ibuf_size = ibs; } if (ctx->obuf != p2) { free(ctx->obuf); ctx->obuf = p2; ctx->obuf_off = 0; ctx->obuf_len = 0; ctx->obuf_size = obs; } break; case BIO_C_DO_STATE_MACHINE: if (b->next_bio == NULL) return (0); BIO_clear_retry_flags(b); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); BIO_copy_next_retry(b); break; case BIO_CTRL_FLUSH: if (b->next_bio == NULL) return (0); if (ctx->obuf_len <= 0) { ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; } for (;;) { BIO_clear_retry_flags(b); if (ctx->obuf_len > 0) { r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]), ctx->obuf_len); BIO_copy_next_retry(b); if (r <= 0) return ((long)r); ctx->obuf_off += r; ctx->obuf_len -= r; } else { ctx->obuf_len = 0; ctx->obuf_off = 0; break; } } ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) || !BIO_set_write_buffer_size(dbio, ctx->obuf_size)) ret = 0; break; default: if (b->next_bio == NULL) return (0); ret = BIO_ctrl(b->next_bio, cmd, num, ptr); break; } return (ret); malloc_error: BIOerror(ERR_R_MALLOC_FAILURE); return (0); }