git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@703 152afb58-edef-0310-8abb-c4023f1b3aa9svn/tags/lighttpd-1.4.6
parent
b795fd36c0
commit
63dceeb0c6
66
src/chunk.c
66
src/chunk.c
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -35,8 +36,10 @@ static chunk *chunk_init(void) {
|
|||
|
||||
c = calloc(1, sizeof(*c));
|
||||
|
||||
/* c->mem overlaps with c->data.file.name */
|
||||
c->data.mem = buffer_init();
|
||||
c->mem = buffer_init();
|
||||
c->file.name = buffer_init();
|
||||
c->file.fd = -1;
|
||||
c->file.mmap.start = MAP_FAILED;
|
||||
c->next = NULL;
|
||||
|
||||
return c;
|
||||
|
@ -45,24 +48,25 @@ static chunk *chunk_init(void) {
|
|||
static void chunk_free(chunk *c) {
|
||||
if (!c) return;
|
||||
|
||||
/* c->data.mem overlaps with c->data.file.name */
|
||||
switch (c->type) {
|
||||
case MEM_CHUNK: buffer_free(c->data.mem); break;
|
||||
case FILE_CHUNK: buffer_free(c->data.file.name); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
buffer_free(c->mem);
|
||||
buffer_free(c->file.name);
|
||||
|
||||
free(c);
|
||||
}
|
||||
|
||||
static void chunk_reset(chunk *c) {
|
||||
if (!c) return;
|
||||
|
||||
/* c->data.mem overlaps with c->data.file.name */
|
||||
switch (c->type) {
|
||||
case MEM_CHUNK: buffer_reset(c->data.mem); break;
|
||||
case FILE_CHUNK: buffer_reset(c->data.file.name); break;
|
||||
default: break;
|
||||
buffer_reset(c->mem);
|
||||
buffer_reset(c->file.name);
|
||||
|
||||
if (c->file.fd != -1) {
|
||||
close(c->file.fd);
|
||||
c->file.fd = -1;
|
||||
}
|
||||
if (MAP_FAILED != c->file.mmap.start) {
|
||||
munmap(c->file.mmap.start, c->file.mmap.length);
|
||||
c->file.mmap.start = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,10 +140,10 @@ void chunkqueue_reset(chunkqueue *cq) {
|
|||
for (c = cq->first; c; c = c->next) {
|
||||
switch(c->type) {
|
||||
case MEM_CHUNK:
|
||||
c->offset = c->data.mem->used - 1;
|
||||
c->offset = c->mem->used - 1;
|
||||
break;
|
||||
case FILE_CHUNK:
|
||||
c->offset = c->data.file.length;
|
||||
c->offset = c->file.length;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -147,6 +151,8 @@ void chunkqueue_reset(chunkqueue *cq) {
|
|||
}
|
||||
|
||||
chunkqueue_remove_finished_chunks(cq);
|
||||
cq->bytes_in = 0;
|
||||
cq->bytes_out = 0;
|
||||
}
|
||||
|
||||
int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
|
||||
|
@ -158,9 +164,9 @@ int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len)
|
|||
|
||||
c->type = FILE_CHUNK;
|
||||
|
||||
buffer_copy_string_buffer(c->data.file.name, fn);
|
||||
c->data.file.offset = offset;
|
||||
c->data.file.length = len;
|
||||
buffer_copy_string_buffer(c->file.name, fn);
|
||||
c->file.offset = offset;
|
||||
c->file.length = len;
|
||||
c->offset = 0;
|
||||
|
||||
chunkqueue_append_chunk(cq, c);
|
||||
|
@ -176,7 +182,7 @@ int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
|
|||
c = chunkqueue_get_unused_chunk(cq);
|
||||
c->type = MEM_CHUNK;
|
||||
c->offset = 0;
|
||||
buffer_copy_string_buffer(c->data.mem, mem);
|
||||
buffer_copy_string_buffer(c->mem, mem);
|
||||
|
||||
chunkqueue_append_chunk(cq, c);
|
||||
|
||||
|
@ -191,7 +197,7 @@ int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
|
|||
c = chunkqueue_get_unused_chunk(cq);
|
||||
c->type = MEM_CHUNK;
|
||||
c->offset = 0;
|
||||
buffer_copy_string_buffer(c->data.mem, mem);
|
||||
buffer_copy_string_buffer(c->mem, mem);
|
||||
|
||||
chunkqueue_prepend_chunk(cq, c);
|
||||
|
||||
|
@ -206,7 +212,7 @@ int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
|
|||
c = chunkqueue_get_unused_chunk(cq);
|
||||
c->type = MEM_CHUNK;
|
||||
c->offset = 0;
|
||||
buffer_copy_string_len(c->data.mem, mem, len - 1);
|
||||
buffer_copy_string_len(c->mem, mem, len - 1);
|
||||
|
||||
chunkqueue_append_chunk(cq, c);
|
||||
|
||||
|
@ -220,11 +226,11 @@ buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
|
|||
|
||||
c->type = MEM_CHUNK;
|
||||
c->offset = 0;
|
||||
buffer_reset(c->data.mem);
|
||||
buffer_reset(c->mem);
|
||||
|
||||
chunkqueue_prepend_chunk(cq, c);
|
||||
|
||||
return c->data.mem;
|
||||
return c->mem;
|
||||
}
|
||||
|
||||
buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
|
||||
|
@ -234,11 +240,11 @@ buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
|
|||
|
||||
c->type = MEM_CHUNK;
|
||||
c->offset = 0;
|
||||
buffer_reset(c->data.mem);
|
||||
buffer_reset(c->mem);
|
||||
|
||||
chunkqueue_append_chunk(cq, c);
|
||||
|
||||
return c->data.mem;
|
||||
return c->mem;
|
||||
}
|
||||
|
||||
off_t chunkqueue_length(chunkqueue *cq) {
|
||||
|
@ -248,10 +254,10 @@ off_t chunkqueue_length(chunkqueue *cq) {
|
|||
for (c = cq->first; c; c = c->next) {
|
||||
switch (c->type) {
|
||||
case MEM_CHUNK:
|
||||
len += c->data.mem->used ? c->data.mem->used - 1 : 0;
|
||||
len += c->mem->used ? c->mem->used - 1 : 0;
|
||||
break;
|
||||
case FILE_CHUNK:
|
||||
len += c->data.file.length;
|
||||
len += c->file.length;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -291,10 +297,10 @@ int chunkqueue_remove_finished_chunks(chunkqueue *cq) {
|
|||
|
||||
switch (c->type) {
|
||||
case MEM_CHUNK:
|
||||
if (c->offset == (off_t)c->data.mem->used - 1) is_finished = 1;
|
||||
if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
|
||||
break;
|
||||
case FILE_CHUNK:
|
||||
if (c->offset == c->data.file.length) is_finished = 1;
|
||||
if (c->offset == c->file.length) is_finished = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
30
src/chunk.h
30
src/chunk.h
|
@ -4,8 +4,7 @@
|
|||
#include "buffer.h"
|
||||
|
||||
typedef struct chunk {
|
||||
/* ok, this one is tricky:
|
||||
*
|
||||
/*
|
||||
* MEM_CHUNK
|
||||
* b: the chunk it self
|
||||
* FILE_CHUNK
|
||||
|
@ -14,18 +13,25 @@ typedef struct chunk {
|
|||
|
||||
enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
|
||||
|
||||
union {
|
||||
buffer *mem;
|
||||
struct {
|
||||
buffer *name;
|
||||
off_t offset;
|
||||
off_t length;
|
||||
} file;
|
||||
} data;
|
||||
/* memchunk */
|
||||
buffer *mem; /* it might be large */
|
||||
|
||||
struct {
|
||||
/* filechunk */
|
||||
buffer *name;
|
||||
off_t offset;
|
||||
off_t length;
|
||||
|
||||
int fd;
|
||||
struct {
|
||||
char *start;
|
||||
size_t length;
|
||||
} mmap;
|
||||
} file;
|
||||
|
||||
/* how many bytes are already handled */
|
||||
|
||||
off_t offset;
|
||||
off_t offset;
|
||||
|
||||
struct chunk *next;
|
||||
} chunk;
|
||||
|
@ -36,6 +42,8 @@ typedef struct {
|
|||
|
||||
chunk *unused;
|
||||
size_t unused_chunks;
|
||||
|
||||
off_t bytes_in, bytes_out;
|
||||
} chunkqueue;
|
||||
|
||||
chunkqueue *chunkqueue_init(void);
|
||||
|
|
|
@ -805,7 +805,7 @@ int connection_handle_read_state(server *srv, connection *con) {
|
|||
for (c = cq->first; c; c = cq->first) {
|
||||
assert(c != c->next);
|
||||
|
||||
if (c->data.mem->used == 0) {
|
||||
if (c->mem->used == 0) {
|
||||
cq->first = c->next;
|
||||
c->next = cq->unused;
|
||||
cq->unused = c;
|
||||
|
@ -830,8 +830,8 @@ int connection_handle_read_state(server *srv, connection *con) {
|
|||
if (con->request.request->used == 0) {
|
||||
buffer b;
|
||||
|
||||
b.ptr = c->data.mem->ptr + c->offset;
|
||||
b.used = c->data.mem->used - c->offset;
|
||||
b.ptr = c->mem->ptr + c->offset;
|
||||
b.used = c->mem->used - c->offset;
|
||||
|
||||
if (NULL != (h_term = buffer_search_rnrn(&b))) {
|
||||
/* \r\n\r\n found
|
||||
|
@ -846,8 +846,8 @@ int connection_handle_read_state(server *srv, connection *con) {
|
|||
c->offset += h_term - b.ptr + 4;
|
||||
} else {
|
||||
/* not found, copy everything */
|
||||
buffer_copy_string_len(con->request.request, c->data.mem->ptr + c->offset, c->data.mem->used - c->offset - 1);
|
||||
c->offset = c->data.mem->used - 1;
|
||||
buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
|
||||
c->offset = c->mem->used - 1;
|
||||
}
|
||||
} else {
|
||||
/* have to take care of overlapping header terminators */
|
||||
|
@ -856,36 +856,36 @@ int connection_handle_read_state(server *srv, connection *con) {
|
|||
char *s = con->request.request->ptr;
|
||||
buffer b;
|
||||
|
||||
b.ptr = c->data.mem->ptr + c->offset;
|
||||
b.used = c->data.mem->used - c->offset;
|
||||
b.ptr = c->mem->ptr + c->offset;
|
||||
b.used = c->mem->used - c->offset;
|
||||
|
||||
if (con->request.request->used - 1 > 3 &&
|
||||
c->data.mem->used > 1 &&
|
||||
c->mem->used > 1 &&
|
||||
s[l-2] == '\r' &&
|
||||
s[l-1] == '\n' &&
|
||||
s[l-0] == '\r' &&
|
||||
c->data.mem->ptr[0] == '\n') {
|
||||
buffer_append_string_len(con->request.request, c->data.mem->ptr + c->offset, 1);
|
||||
c->mem->ptr[0] == '\n') {
|
||||
buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
|
||||
c->offset += 1;
|
||||
|
||||
h_term = con->request.request->ptr;
|
||||
} else if (con->request.request->used - 1 > 2 &&
|
||||
c->data.mem->used > 2 &&
|
||||
c->mem->used > 2 &&
|
||||
s[l-1] == '\r' &&
|
||||
s[l-0] == '\n' &&
|
||||
c->data.mem->ptr[0] == '\r' &&
|
||||
c->data.mem->ptr[1] == '\n') {
|
||||
buffer_append_string_len(con->request.request, c->data.mem->ptr + c->offset, 2);
|
||||
c->mem->ptr[0] == '\r' &&
|
||||
c->mem->ptr[1] == '\n') {
|
||||
buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
|
||||
c->offset += 2;
|
||||
|
||||
h_term = con->request.request->ptr;
|
||||
} else if (con->request.request->used - 1 > 1 &&
|
||||
c->data.mem->used > 3 &&
|
||||
c->mem->used > 3 &&
|
||||
s[l-0] == '\r' &&
|
||||
c->data.mem->ptr[0] == '\n' &&
|
||||
c->data.mem->ptr[1] == '\r' &&
|
||||
c->data.mem->ptr[2] == '\n') {
|
||||
buffer_append_string_len(con->request.request, c->data.mem->ptr + c->offset, 3);
|
||||
c->mem->ptr[0] == '\n' &&
|
||||
c->mem->ptr[1] == '\r' &&
|
||||
c->mem->ptr[2] == '\n') {
|
||||
buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
|
||||
c->offset += 3;
|
||||
|
||||
h_term = con->request.request->ptr;
|
||||
|
@ -895,19 +895,19 @@ int connection_handle_read_state(server *srv, connection *con) {
|
|||
*/
|
||||
|
||||
buffer_append_string_len(con->request.request,
|
||||
c->data.mem->ptr + c->offset,
|
||||
c->mem->ptr + c->offset,
|
||||
c->offset + h_term - b.ptr + 4);
|
||||
|
||||
/* the buffer has been read up to the terminator */
|
||||
c->offset += h_term - b.ptr + 4;
|
||||
} else {
|
||||
/* not found, copy everything */
|
||||
buffer_append_string_len(con->request.request, c->data.mem->ptr + c->offset, c->data.mem->used - c->offset - 1);
|
||||
c->offset = c->data.mem->used - 1;
|
||||
buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
|
||||
c->offset = c->mem->used - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->offset + 1 == c->data.mem->used) {
|
||||
if (c->offset + 1 == c->mem->used) {
|
||||
/* chunk is empty, move it to unused */
|
||||
cq->first = c->next;
|
||||
c->next = cq->unused;
|
||||
|
@ -933,17 +933,17 @@ int connection_handle_read_state(server *srv, connection *con) {
|
|||
weWant = con->request.content_length - (con->request.content->used ? con->request.content->used - 1 : 0);
|
||||
/* without the terminating \0 */
|
||||
|
||||
assert(c->data.mem->used);
|
||||
assert(c->mem->used);
|
||||
|
||||
weHave = c->data.mem->used - c->offset - 1;
|
||||
weHave = c->mem->used - c->offset - 1;
|
||||
|
||||
toRead = weHave > weWant ? weWant : weHave;
|
||||
|
||||
buffer_append_string_len(con->request.content, c->data.mem->ptr + c->offset, toRead);
|
||||
buffer_append_string_len(con->request.content, c->mem->ptr + c->offset, toRead);
|
||||
|
||||
c->offset += toRead;
|
||||
|
||||
if (c->offset + 1 >= c->data.mem->used) {
|
||||
if (c->offset + 1 >= c->mem->used) {
|
||||
/* chunk is empty, move it to unused */
|
||||
|
||||
cq->first = c->next;
|
||||
|
|
|
@ -1951,9 +1951,9 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p
|
|||
/* get at least the FastCGI header */
|
||||
for (c = hctx->rb->first; c; c = c->next) {
|
||||
if (packet->b->used == 0) {
|
||||
buffer_copy_string_len(packet->b, c->data.mem->ptr + c->offset, c->data.mem->used - c->offset - 1);
|
||||
buffer_copy_string_len(packet->b, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
|
||||
} else {
|
||||
buffer_append_string_len(packet->b, c->data.mem->ptr + c->offset, c->data.mem->used - c->offset - 1);
|
||||
buffer_append_string_len(packet->b, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
|
||||
}
|
||||
|
||||
if (packet->b->used >= sizeof(*header) + 1) break;
|
||||
|
@ -1979,25 +1979,20 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p
|
|||
/* the first bytes in packet->b are the header */
|
||||
offset = sizeof(*header);
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "sddd", "FastCGI: got header:", packet->len, packet->request_id, packet->type);
|
||||
|
||||
/* ->b should only be the content */
|
||||
buffer_reset(packet->b);
|
||||
|
||||
if (packet->len) {
|
||||
/* copy the content */
|
||||
for (; c && (packet->b->used < packet->len + 1); c = c->next) {
|
||||
toread = c->data.mem->used - c->offset - offset - 1 > packet->len ? packet->len : c->data.mem->used - c->offset - offset - 1;
|
||||
toread = c->mem->used - c->offset - offset - 1 > packet->len ? packet->len : c->mem->used - c->offset - offset - 1;
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "sdd", "FastCGI: reading content:", packet->b->used, toread);
|
||||
|
||||
buffer_append_string_len(packet->b, c->data.mem->ptr + c->offset + offset, toread);
|
||||
buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, toread);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (packet->b->used < packet->len + 1) {
|
||||
/* we didn't got the full packet */
|
||||
log_error_write(srv, __FILE__, __LINE__, "sdd", "FastCGI: not the full packet", packet->b->used, packet->len);
|
||||
|
||||
buffer_free(packet->b);
|
||||
return -1;
|
||||
|
@ -2010,10 +2005,10 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p
|
|||
/* tag the chunks as read */
|
||||
toread = packet->len + sizeof(FCGI_Header);
|
||||
for (c = hctx->rb->first; c && toread; c = c->next) {
|
||||
if (c->data.mem->used - c->offset - 1 <= toread) {
|
||||
if (c->mem->used - c->offset - 1 <= toread) {
|
||||
/* we read this whole buffer, move it to unused */
|
||||
toread -= c->data.mem->used - c->offset - 1;
|
||||
c->offset = c->data.mem->used - 1; /* everthing has been written */
|
||||
toread -= c->mem->used - c->offset - 1;
|
||||
c->offset = c->mem->used - 1; /* everthing has been written */
|
||||
} else {
|
||||
c->offset += toread;
|
||||
toread = 0;
|
||||
|
|
|
@ -53,12 +53,12 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, chunkqu
|
|||
tc = tc->next, num_chunks++);
|
||||
|
||||
for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
|
||||
if (tc->data.mem->used == 0) {
|
||||
chunks[i].iov_base = tc->data.mem->ptr;
|
||||
if (tc->mem->used == 0) {
|
||||
chunks[i].iov_base = tc->mem->ptr;
|
||||
chunks[i].iov_len = 0;
|
||||
} else {
|
||||
offset = tc->data.mem->ptr + tc->offset;
|
||||
toSend = tc->data.mem->used - 1 - tc->offset;
|
||||
offset = tc->mem->ptr + tc->offset;
|
||||
toSend = tc->mem->used - 1 - tc->offset;
|
||||
|
||||
chunks[i].iov_base = offset;
|
||||
|
||||
|
@ -101,7 +101,6 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, chunkqu
|
|||
/* written */
|
||||
r -= chunks[i].iov_len;
|
||||
tc->offset += chunks[i].iov_len;
|
||||
con->bytes_written += chunks[i].iov_len;
|
||||
|
||||
if (chunk_finished) {
|
||||
/* skip the chunks from further touches */
|
||||
|
@ -115,12 +114,13 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, chunkqu
|
|||
/* partially written */
|
||||
|
||||
tc->offset += r;
|
||||
con->bytes_written += r;
|
||||
chunk_finished = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
cq->bytes_out += r;
|
||||
con->bytes_written += r;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -129,33 +129,34 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, chunkqu
|
|||
off_t offset;
|
||||
size_t toSend;
|
||||
stat_cache_entry *sce = NULL;
|
||||
int ifd;
|
||||
|
||||
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->data.file.name, &sce)) {
|
||||
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
strerror(errno), c->data.file.name);
|
||||
strerror(errno), c->file.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = c->data.file.offset + c->offset;
|
||||
offset = c->file.offset + c->offset;
|
||||
/* limit the toSend to 2^31-1 bytes in a chunk */
|
||||
toSend = c->data.file.length - c->offset > ((1 << 30) - 1) ?
|
||||
((1 << 30) - 1) : c->data.file.length - c->offset;
|
||||
toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
|
||||
((1 << 30) - 1) : c->file.length - c->offset;
|
||||
|
||||
if (offset > sce->st.st_size) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->data.file.name);
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == (ifd = open(c->data.file.name->ptr, O_RDONLY))) {
|
||||
|
||||
/* open file if not already opened */
|
||||
if (-1 == c->file.fd &&
|
||||
-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Linux sendfile() */
|
||||
if (-1 == (r = sendfile(fd, ifd, &offset, toSend))) {
|
||||
if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
case EINTR:
|
||||
|
@ -163,21 +164,19 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, chunkqu
|
|||
break;
|
||||
case EPIPE:
|
||||
case ECONNRESET:
|
||||
close(ifd);
|
||||
return -2;
|
||||
default:
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssd",
|
||||
"sendfile failed:", strerror(errno), fd);
|
||||
close(ifd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
close(ifd);
|
||||
|
||||
c->offset += r;
|
||||
con->bytes_written += r;
|
||||
cq->bytes_out += r;
|
||||
|
||||
if (c->offset == c->data.file.length) {
|
||||
if (c->offset == c->file.length) {
|
||||
chunk_finished = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,13 +38,13 @@ int network_write_chunkqueue_write(server *srv, connection *con, chunkqueue *cq)
|
|||
size_t toSend;
|
||||
ssize_t r;
|
||||
|
||||
if (c->data.mem->used == 0) {
|
||||
if (c->mem->used == 0) {
|
||||
chunk_finished = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
offset = c->data.mem->ptr + c->offset;
|
||||
toSend = c->data.mem->used - 1 - c->offset;
|
||||
offset = c->mem->ptr + c->offset;
|
||||
toSend = c->mem->used - 1 - c->offset;
|
||||
#ifdef __WIN32
|
||||
if ((r = send(fd, offset, toSend, 0)) < 0) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
|
||||
|
@ -62,7 +62,7 @@ int network_write_chunkqueue_write(server *srv, connection *con, chunkqueue *cq)
|
|||
c->offset += r;
|
||||
con->bytes_written += r;
|
||||
|
||||
if (c->offset == (off_t)c->data.mem->used - 1) {
|
||||
if (c->offset == (off_t)c->mem->used - 1) {
|
||||
chunk_finished = 1;
|
||||
}
|
||||
|
||||
|
@ -78,22 +78,22 @@ int network_write_chunkqueue_write(server *srv, connection *con, chunkqueue *cq)
|
|||
stat_cache_entry *sce = NULL;
|
||||
int ifd;
|
||||
|
||||
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->data.file.name, &sce)) {
|
||||
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
strerror(errno), c->data.file.name);
|
||||
strerror(errno), c->file.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = c->data.file.offset + c->offset;
|
||||
toSend = c->data.file.length - c->offset;
|
||||
offset = c->file.offset + c->offset;
|
||||
toSend = c->file.length - c->offset;
|
||||
|
||||
if (offset > sce->st.st_size) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->data.file.name);
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == (ifd = open(c->data.file.name->ptr, O_RDONLY))) {
|
||||
if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
|
||||
|
||||
return -1;
|
||||
|
@ -137,7 +137,7 @@ int network_write_chunkqueue_write(server *srv, connection *con, chunkqueue *cq)
|
|||
c->offset += r;
|
||||
con->bytes_written += r;
|
||||
|
||||
if (c->offset == c->data.file.length) {
|
||||
if (c->offset == c->file.length) {
|
||||
chunk_finished = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,12 +75,12 @@ int network_write_chunkqueue_writev(server *srv, connection *con, chunkqueue *cq
|
|||
for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
|
||||
|
||||
for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
|
||||
if (tc->data.mem->used == 0) {
|
||||
chunks[i].iov_base = tc->data.mem->ptr;
|
||||
if (tc->mem->used == 0) {
|
||||
chunks[i].iov_base = tc->mem->ptr;
|
||||
chunks[i].iov_len = 0;
|
||||
} else {
|
||||
offset = tc->data.mem->ptr + tc->offset;
|
||||
toSend = tc->data.mem->used - 1 - tc->offset;
|
||||
offset = tc->mem->ptr + tc->offset;
|
||||
toSend = tc->mem->used - 1 - tc->offset;
|
||||
|
||||
chunks[i].iov_base = offset;
|
||||
|
||||
|
@ -123,7 +123,6 @@ int network_write_chunkqueue_writev(server *srv, connection *con, chunkqueue *cq
|
|||
/* written */
|
||||
r -= chunks[i].iov_len;
|
||||
tc->offset += chunks[i].iov_len;
|
||||
con->bytes_written += chunks[i].iov_len;
|
||||
|
||||
if (chunk_finished) {
|
||||
/* skip the chunks from further touches */
|
||||
|
@ -137,89 +136,82 @@ int network_write_chunkqueue_writev(server *srv, connection *con, chunkqueue *cq
|
|||
/* partially written */
|
||||
|
||||
tc->offset += r;
|
||||
con->bytes_written += r;
|
||||
chunk_finished = 0;
|
||||
#if 0
|
||||
log_error_write(srv, __FILE__, __LINE__, "sdd",
|
||||
"(debug) partially write: ", r, fd);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cq->bytes_out += r;
|
||||
con->bytes_written += r;
|
||||
|
||||
break;
|
||||
}
|
||||
case FILE_CHUNK: {
|
||||
#ifdef USE_MMAP
|
||||
char *p = NULL;
|
||||
#endif
|
||||
ssize_t r;
|
||||
off_t offset;
|
||||
size_t toSend;
|
||||
stat_cache_entry *sce = NULL;
|
||||
int ifd;
|
||||
|
||||
switch (stat_cache_get_entry(srv, con, c->data.file.name, &sce)) {
|
||||
case HANDLER_COMEBACK:
|
||||
case HANDLER_GO_ON:
|
||||
offset = c->data.file.offset + c->offset;
|
||||
toSend = c->data.file.length - c->offset;
|
||||
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
strerror(errno), c->file.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = c->file.offset + c->offset;
|
||||
toSend = c->file.length - c->offset;
|
||||
|
||||
if (offset > sce->st.st_size) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
"file was shrinked:", c->data.file.name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == (ifd = open(c->data.file.name->ptr, O_RDONLY))) {
|
||||
if (offset > sce->st.st_size) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
"file was shrinked:", c->file.name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (c->file.mmap.start == MAP_FAILED) {
|
||||
if (-1 == c->file.fd && /* open the file if not already open */
|
||||
-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
|
||||
if (MAP_FAILED == (c->file.mmap.start = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
|
||||
strerror(errno), c->data.file.name, ifd);
|
||||
strerror(errno), c->file.name, c->file.fd);
|
||||
|
||||
close(ifd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(ifd);
|
||||
|
||||
if ((r = write(fd, p + offset, toSend)) <= 0) {
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
case EINTR:
|
||||
r = 0;
|
||||
break;
|
||||
case EPIPE:
|
||||
case ECONNRESET:
|
||||
return -2;
|
||||
default:
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssd",
|
||||
"write failed:", strerror(errno), fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
munmap(p, sce->st.st_size);
|
||||
|
||||
break;
|
||||
default:
|
||||
log_error_write(srv, __FILE__, __LINE__, "sb",
|
||||
strerror(errno), c->data.file.name);
|
||||
return -1;
|
||||
close(c->file.fd);
|
||||
c->file.fd = -1;
|
||||
|
||||
/* chunk_reset() or chunk_free() will cleanup for us */
|
||||
}
|
||||
|
||||
if ((r = write(fd, c->file.mmap.start + offset, toSend)) < 0) {
|
||||
switch (errno) {
|
||||
case EAGAIN:
|
||||
case EINTR:
|
||||
r = 0;
|
||||
break;
|
||||
case EPIPE:
|
||||
case ECONNRESET:
|
||||
return -2;
|
||||
default:
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssd",
|
||||
"write failed:", strerror(errno), fd);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
c->offset += r;
|
||||
con->bytes_written += r;
|
||||
cq->bytes_out += r;
|
||||
|
||||
if (c->offset == c->data.file.length) {
|
||||
if (c->offset == c->file.length) {
|
||||
chunk_finished = 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue