Browse Source

[core] read up-to fixed size chunk before fionread

personal/stbuehler/ci-build
Glenn Strauss 3 years ago
parent
commit
de73b190a4
  1. 30
      src/chunk.c
  2. 2
      src/chunk.h
  3. 161
      src/connections.c
  4. 5
      src/mod_openssl.c

30
src/chunk.c

@ -421,21 +421,25 @@ char * chunkqueue_get_memory(chunkqueue *cq, size_t *len) {
return b->ptr;
}
void chunkqueue_use_memory(chunkqueue *cq, size_t len) {
buffer *b;
void chunkqueue_use_memory(chunkqueue *cq, chunk *ckpt, size_t len) {
buffer *b = cq->last->mem;
force_assert(NULL != cq);
force_assert(NULL != cq->last && MEM_CHUNK == cq->last->type);
b = cq->last->mem;
if (len > 0) {
buffer_commit(b, len);
cq->bytes_in += len;
if (cq->last == ckpt || NULL == ckpt || MEM_CHUNK != ckpt->type
|| len > chunk_buffer_string_space(ckpt->mem)) return;
if (len > 0) {
buffer_commit(b, len);
cq->bytes_in += len;
} else if (chunk_buffer_string_is_empty(b)) {
/* scan chunkqueue to remove empty last chunk
* (generally not expecting a deep queue) */
chunkqueue_remove_empty_chunks(cq);
}
buffer_append_string_buffer(ckpt->mem, b);
}
else if (!chunk_buffer_string_is_empty(b)) { /*(cq->last == ckpt)*/
return; /* last chunk is not empty */
}
/* remove empty last chunk */
chunk_release(cq->last);
cq->last = ckpt;
*(ckpt ? &ckpt->next : &cq->first) = NULL;
}
void chunkqueue_set_tempdirs_default (const array *tempdirs, off_t upload_temp_file_size) {

2
src/chunk.h

@ -100,7 +100,7 @@ int chunkqueue_append_mem_to_tempfile(chunkqueue *cq, const char *mem, size_t le
__attribute_returns_nonnull__
char * chunkqueue_get_memory(chunkqueue *cq, size_t *len);
/* commit len bytes of mem obtained from chunkqueue_get_memory() */
void chunkqueue_use_memory(chunkqueue *cq, size_t len);
void chunkqueue_use_memory(chunkqueue *cq, chunk *ckpt, size_t len);
/* mark first "len" bytes as written (incrementing chunk offsets)
* and remove finished chunks

161
src/connections.c

@ -1001,90 +1001,95 @@ connection *connection_accept(server *srv, server_socket *srv_socket) {
}
/* 0: everything ok, -1: error, -2: con closed */
static int connection_read_cq(connection *con, chunkqueue *cq, off_t max_bytes) {
ssize_t len;
char *mem = NULL;
size_t mem_len = 0;
force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
force_assert(max_bytes == MAX_READ_LIMIT); /*(code transform assumption; minimize diff)*/
/* check avail data to read and obtain memory into which to read
* fill previous chunk if it has sufficient space
* (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz)
*/
{
int frd;
if (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd)) {
mem_len = (frd < MAX_READ_LIMIT) ? (size_t)frd : MAX_READ_LIMIT;
}
}
mem = chunkqueue_get_memory(con->read_queue, &mem_len);
#if defined(__WIN32)
len = recv(con->fd, mem, mem_len, 0);
#else
len = read(con->fd, mem, mem_len);
#endif /* __WIN32 */
chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
if (len < 0) {
con->is_readable = 0;
#if defined(__WIN32)
{
int lastError = WSAGetLastError();
switch (lastError) {
case EAGAIN:
return 0;
case EINTR:
/* we have been interrupted before we could read */
con->is_readable = 1;
return 0;
case ECONNRESET:
/* suppress logging for this error, expected for keep-alive */
break;
default:
log_error(con->conf.errh, __FILE__, __LINE__, "connection closed - recv failed: %d", lastError);
break;
}
}
#else /* __WIN32 */
switch (errno) {
case EAGAIN:
return 0;
case EINTR:
/* we have been interrupted before we could read */
con->is_readable = 1;
return 0;
case ECONNRESET:
/* suppress logging for this error, expected for keep-alive */
break;
default:
log_perror(con->conf.errh, __FILE__, __LINE__, "connection closed - read failed");
break;
}
#endif /* __WIN32 */
__attribute_cold__
static int connection_read_cq_err(connection *con) {
#if defined(__WIN32)
int lastError = WSAGetLastError();
switch (lastError) {
case EAGAIN:
return 0;
case EINTR:
/* we have been interrupted before we could read */
con->is_readable = 1;
return 0;
case ECONNRESET:
/* suppress logging for this error, expected for keep-alive */
break;
default:
log_error(con->conf.errh, __FILE__, __LINE__,
"connection closed - recv failed: %d", lastError);
break;
}
#else /* __WIN32 */
switch (errno) {
case EAGAIN:
return 0;
case EINTR:
/* we have been interrupted before we could read */
con->is_readable = 1;
return 0;
case ECONNRESET:
/* suppress logging for this error, expected for keep-alive */
break;
default:
log_perror(con->conf.errh, __FILE__, __LINE__,
"connection closed - read failed");
break;
}
#endif /* __WIN32 */
connection_set_state(con, CON_STATE_ERROR);
connection_set_state(con, CON_STATE_ERROR);
return -1;
}
return -1;
} else if (len == 0) {
con->is_readable = 0;
/* the other end close the connection -> KEEP-ALIVE */
/* pipelining */
/* 0: everything ok, -1: error, -2: con closed */
static int connection_read_cq(connection *con, chunkqueue *cq, off_t max_bytes) {
ssize_t len;
size_t mem_len = 0;
force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
/*force_assert(max_bytes == MAX_READ_LIMIT);*//*(code transform assumption; minimize diff)*/
return -2;
} else if (len != (ssize_t) mem_len) {
/* we got less then expected, wait for the next fd-event */
do {
/* obtain chunk memory into which to read
* fill previous chunk if it has a reasonable amount of space available
* (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz)
*/
chunk *ckpt = con->read_queue->last;
char * const mem = chunkqueue_get_memory(con->read_queue, &mem_len);
if (mem_len > (size_t)max_bytes) mem_len = (size_t)max_bytes;
#if defined(__WIN32)
len = recv(con->fd, mem, mem_len, 0);
#else
len = read(con->fd, mem, mem_len);
#endif /* __WIN32 */
chunkqueue_use_memory(con->read_queue, ckpt, len > 0 ? len : 0);
if (len != (ssize_t)mem_len) {
/* we got less then expected, wait for the next fd-event */
con->is_readable = 0;
if (len > 0) {
con->bytes_read += len;
return 0;
}
else if (0 == len) /* other end close connection -> KEEP-ALIVE */
return -2; /* (pipelining) */
else
return connection_read_cq_err(con);
}
con->is_readable = 0;
}
con->bytes_read += len;
max_bytes -= len;
con->bytes_read += len;
return 0;
int frd;
mem_len = (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd))
? (frd < max_bytes) ? (size_t)frd : (size_t)max_bytes
: 0;
} while (max_bytes);
return 0;
}

5
src/mod_openssl.c

@ -1898,14 +1898,15 @@ connection_read_cq_ssl (connection *con, chunkqueue *cq, off_t max_bytes)
do {
len = SSL_pending(hctx->ssl);
mem_len = len < 2048 ? 2048 : (size_t)len;
chunk * const ckpt = con->read_queue->last;
mem = chunkqueue_get_memory(con->read_queue, &mem_len);
len = SSL_read(hctx->ssl, mem, mem_len);
if (len > 0) {
chunkqueue_use_memory(con->read_queue, len);
chunkqueue_use_memory(con->read_queue, ckpt, len);
con->bytes_read += len;
} else {
chunkqueue_use_memory(con->read_queue, 0);
chunkqueue_use_memory(con->read_queue, ckpt, 0);
}
if (hctx->renegotiations > 1

Loading…
Cancel
Save