static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt) { SSL *ssl; conn_rec *c; int rc; if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) { rc = SSL_writev(ssl, iov, iovcnt); /* * Simulate an EINTR in case OpenSSL wants to write more. */ if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE) errno = EINTR; /* * Log SSL errors */ if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) { c = (conn_rec *)SSL_get_app_data(ssl); ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR, "SSL error on writing data"); } /* * writev(2) returns only the generic error number -1 */ if (rc < 0) rc = -1; } else rc = writev(fb->fd, iov, iovcnt); return rc; }
int calipso_reply_send_writev(calipso_reply_t *reply) { struct iovec *iovv, iov[IOV_MAX]; cpo_array_t arr; dllist_t *l; struct chunk_ctx *cc; chunks_t *cf = reply->out_filter; calipso_client_t *client; int prev_send, sent = 0; int send = 0; //int complete = 0; int nw, block; arr.elem_size = sizeof(struct iovec); arr.max = IOV_MAX; arr.v = iov; client = calipso_reply_get_client(reply); for (;;) { arr.num = 0; iovv = NULL; prev_send = send; for (l = cf->list; l && (cc = l->data); l = l->next) { if (arr.num == IOV_MAX) { break; } if (cc->size) { send += cc->size; iovv = cpo_array_push(&arr); iovv->iov_base = cc->b; iovv->iov_len = cc->size; } } #ifdef USE_SSL if (client->ssl) nw = SSL_writev(client->ssl, arr.v, arr.num); else #endif nw = writev(client->csocket, arr.v, arr.num); if (nw < 0) { if (nw == -1 && errno == EWOULDBLOCK) { break; } else { reply->bytes_to_send = reply->bytes_sent; reply->out_filter->total_bytes = 0; TRACE("writev error %s\n", strerror(errno)); cpo_log_error(calipso->log, "writev error %s\n", strerror(errno)); break; } } sent = nw > 0 ? nw : 0; if (send - prev_send == sent) { printf("Complete %d\n", send - prev_send); //complete =1; } //printf("nwritten %d bytes_sent %d\n", nw , reply->bytes_sent); reply->bytes_sent += sent; reply->out_filter->total_bytes -= sent; if (!reply->out_filter->total_bytes) { //printf("Break loop\n"); break; } block = 0; FOREACH_CHUNK_CTX(l,cf,cc) { //dllist_t *ll = l; block += cc->size; if (block <= sent) { cc->b += cc->size; cc->size -= cc->size; //ll = dllist_find_release(ll, cc); //l = ll; } if (block > sent) { int last = block - sent; int len = cc->size - last; cc->b += len; cc->size -= len; reply->out_filter = cf; return 1; } } } //for;;