Browse Source

[chunk/network] use glib error system to report errors (instead of using virtualrequest context)

personal/stbuehler/wip
Stefan Bühler 10 years ago
parent
commit
b1c45e6a8f
  1. 23
      include/lighttpd/chunk.h
  2. 8
      include/lighttpd/chunk_parser.h
  3. 17
      include/lighttpd/network.h
  4. 80
      src/main/chunk.c
  5. 18
      src/main/chunk_parser.c
  6. 14
      src/main/connection.c
  7. 8
      src/main/filter_buffer_on_disk.c
  8. 7
      src/main/filter_chunked.c
  9. 17
      src/main/http_request_parser.rl
  10. 17
      src/main/http_response_parser.rl
  11. 18
      src/main/network.c
  12. 34
      src/main/network_sendfile.c
  13. 6
      src/main/network_write.c
  14. 6
      src/main/network_writev.c
  15. 10
      src/modules/mod_cache_disk_etag.c
  16. 16
      src/modules/mod_deflate.c
  17. 24
      src/modules/mod_fastcgi.c
  18. 10
      src/modules/mod_gnutls.c
  19. 8
      src/modules/mod_memcached.c
  20. 11
      src/modules/mod_openssl.c
  21. 20
      src/modules/mod_proxy.c
  22. 20
      src/modules/mod_scgi.c
  23. 2
      src/unittests/test-chunk.c

23
include/lighttpd/chunk.h

@ -50,7 +50,7 @@ struct liChunk {
GList cq_link;
};
typedef void (*liCQLimitNnotifyCB)(liVRequest *vr, gpointer context, gboolean locked);
typedef void (*liCQLimitNotifyCB)(liVRequest *vr, gpointer context, gboolean locked);
struct liCQLimit {
gint refcount;
liVRequest *vr;
@ -60,7 +60,7 @@ struct liCQLimit {
ev_io *io_watcher;
liCQLimitNnotifyCB notify; /* callback to reactivate input */
liCQLimitNotifyCB notify; /* callback to reactivate input */
gpointer context;
};
@ -79,18 +79,21 @@ struct liChunkIter {
GList *element;
};
#define LI_CHUNK_ERROR li_chunk_error_quark()
LI_API GQuark li_chunk_error_quark(void);
/******************
* chunkfile *
******************/
liChunkFile *li_chunkfile_new(GString *name, int fd, gboolean is_temp);
void li_chunkfile_acquire(liChunkFile *cf);
void li_chunkfile_release(liChunkFile *cf);
LI_API liChunkFile *li_chunkfile_new(GString *name, int fd, gboolean is_temp);
LI_API void li_chunkfile_acquire(liChunkFile *cf);
LI_API void li_chunkfile_release(liChunkFile *cf);
/* open the file cf->name if it is not already opened for reading
* may return HANDLER_GO_ON, HANDLER_ERROR
*/
LI_API liHandlerResult li_chunkfile_open(liVRequest *vr, liChunkFile *cf);
LI_API liHandlerResult li_chunkfile_open(liChunkFile *cf, GError **err);
/******************
* chunk iterator *
@ -104,12 +107,12 @@ INLINE goffset li_chunkiter_length(liChunkIter iter);
* but needs to do io in case of FILE_CHUNK; the data is _not_ marked as "done"
* may return HANDLER_GO_ON, HANDLER_ERROR
*/
LI_API liHandlerResult li_chunkiter_read(liVRequest *vr, liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len);
LI_API liHandlerResult li_chunkiter_read(liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len, GError **err);
/* same as li_chunkiter_read, but tries mmap() first and falls back to read();
* as accessing mmap()-ed areas may result in SIGBUS, you have to handle that signal somehow.
*/
LI_API liHandlerResult li_chunkiter_read_mmap(liVRequest *vr, liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len);
LI_API liHandlerResult li_chunkiter_read_mmap(liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len, GError **err);
/******************
* chunk *
@ -198,8 +201,8 @@ INLINE liChunkIter li_chunkqueue_iter(liChunkQueue *cq);
INLINE liChunk* li_chunkqueue_first_chunk(liChunkQueue *cq);
LI_API gboolean li_chunkqueue_extract_to(liVRequest *vr, liChunkQueue *cq, goffset len, GString *dest);
LI_API gboolean li_chunkqueue_extract_to_bytearr(liVRequest *vr, liChunkQueue *cq, goffset len, GByteArray *dest);
LI_API gboolean li_chunkqueue_extract_to(liChunkQueue *cq, goffset len, GString *dest, GError **err);
LI_API gboolean li_chunkqueue_extract_to_bytearr(liChunkQueue *cq, goffset len, GByteArray *dest, GError **err);
/* helper functions to append to the last BUFFER_CHUNK of a chunkqueue */

8
include/lighttpd/chunk_parser.h

@ -28,12 +28,12 @@ struct liChunkParserMark {
LI_API void li_chunk_parser_init(liChunkParserCtx *ctx, liChunkQueue *cq);
LI_API void li_chunk_parser_reset(liChunkParserCtx *ctx);
LI_API liHandlerResult li_chunk_parser_prepare(liChunkParserCtx *ctx);
LI_API liHandlerResult li_chunk_parser_next(liVRequest *vr, liChunkParserCtx *ctx, char **p, char **pe);
LI_API liHandlerResult li_chunk_parser_next(liChunkParserCtx *ctx, char **p, char **pe, GError **err);
LI_API void li_chunk_parser_done(liChunkParserCtx *ctx, goffset len);
/* extract [from..to) */
LI_API gboolean li_chunk_extract_to(liVRequest *vr, liChunkParserMark from, liChunkParserMark to, GString *dest);
LI_API GString* li_chunk_extract(liVRequest *vr, liChunkParserMark from, liChunkParserMark to);
LI_API gboolean li_chunk_extract_to(liChunkParserMark from, liChunkParserMark to, GString *dest, GError **err);
LI_API GString* li_chunk_extract(liChunkParserMark from, liChunkParserMark to, GError **err);
INLINE liChunkParserMark li_chunk_parser_getmark(liChunkParserCtx *ctx, const char *fpc);
@ -49,6 +49,6 @@ INLINE liChunkParserMark li_chunk_parser_getmark(liChunkParserCtx *ctx, const ch
return m;
}
#define GETMARK(FPC) (li_chunk_parser_getmark(&ctx->chunk_ctx, FPC))
#define LI_GETMARK(FPC) (li_chunk_parser_getmark(&ctx->chunk_ctx, FPC))
#endif

17
include/lighttpd/network.h

@ -9,30 +9,33 @@
# define USE_SENDFILE
#endif
#define LI_NETWORK_ERROR li_network_error_quark()
LI_API GQuark li_network_error_quark(void);
/** repeats write after EINTR */
LI_API ssize_t li_net_write(int fd, void *buf, ssize_t nbyte);
/** repeats read after EINTR */
LI_API ssize_t li_net_read(int fd, void *buf, ssize_t nbyte);
LI_API liNetworkStatus li_network_write(liVRequest *vr, int fd, liChunkQueue *cq, goffset write_max);
LI_API liNetworkStatus li_network_read(liVRequest *vr, int fd, liChunkQueue *cq, liBuffer **buffer);
LI_API liNetworkStatus li_network_write(int fd, liChunkQueue *cq, goffset write_max, GError **err);
LI_API liNetworkStatus li_network_read(int fd, liChunkQueue *cq, liBuffer **buffer, GError **err);
/* use writev for mem chunks, buffered read/write for files */
LI_API liNetworkStatus li_network_write_writev(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max);
LI_API liNetworkStatus li_network_write_writev(int fd, liChunkQueue *cq, goffset *write_max, GError **err);
#ifdef USE_SENDFILE
/* use sendfile for files, writev for mem chunks */
LI_API liNetworkStatus li_network_write_sendfile(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max);
LI_API liNetworkStatus li_network_write_sendfile(int fd, liChunkQueue *cq, goffset *write_max, GError **err);
#endif
/* write backends */
LI_API liNetworkStatus li_network_backend_write(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max);
LI_API liNetworkStatus li_network_backend_writev(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max);
LI_API liNetworkStatus li_network_backend_write(int fd, liChunkQueue *cq, goffset *write_max, GError **err);
LI_API liNetworkStatus li_network_backend_writev(int fd, liChunkQueue *cq, goffset *write_max, GError **err);
#define LI_NETWORK_FALLBACK(f, write_max) do { \
liNetworkStatus res; \
switch(res = f(vr, fd, cq, write_max)) { \
switch(res = f(fd, cq, write_max, err)) { \
case LI_NETWORK_STATUS_SUCCESS: \
break; \
default: \

80
src/main/chunk.c

@ -4,6 +4,10 @@
#include <sys/stat.h>
#include <fcntl.h>
GQuark li_chunk_error_quark(void) {
return g_quark_from_string("g-chunk-error-quark");
}
/******************
* chunkfile *
******************/
@ -43,18 +47,20 @@ void li_chunkfile_release(liChunkFile *cf) {
/* open the file cf->name if it is not already opened for reading
* may return HANDLER_GO_ON, HANDLER_ERROR
*/
liHandlerResult li_chunkfile_open(liVRequest *vr, liChunkFile *cf) {
if (!cf) return LI_HANDLER_ERROR;
liHandlerResult li_chunkfile_open(liChunkFile *cf, GError **err) {
g_return_val_if_fail (err == NULL || *err == NULL, LI_HANDLER_ERROR);
if (NULL == cf) {
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkfile_open: cf is NULL");
return LI_HANDLER_ERROR;
}
if (-1 != cf->fd) return LI_HANDLER_GO_ON;
if (!cf->name) {
VR_ERROR(vr, "%s", "Missing filename for FILE_CHUNK");
if (NULL == cf->name) {
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkfile_open: Missing filename");
return LI_HANDLER_ERROR;
}
if (-1 == (cf->fd = open(cf->name->str, O_RDONLY))) {
if (EMFILE == errno) {
li_server_out_of_fds(vr->wrk->srv);
}
VR_ERROR(vr, "Couldn't open file '%s': %s", GSTR_SAFE_STR(cf->name), g_strerror(errno));
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkfile_open: Couldn't open file '%s': %s", GSTR_SAFE_STR(cf->name), g_strerror(errno));
return LI_HANDLER_ERROR;
}
#ifdef FD_CLOEXEC
@ -64,7 +70,7 @@ liHandlerResult li_chunkfile_open(liVRequest *vr, liChunkFile *cf) {
/* tell the kernel that we want to stream the file */
if (-1 == posix_fadvise(cf->fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
if (ENOSYS != errno) {
VR_ERROR(vr, "posix_fadvise failed for '%s': %s (%i)", GSTR_SAFE_STR(cf->name), g_strerror(errno), cf->fd);
/* g_debug("posix_fadvise failed for '%s': %s (%i)", GSTR_SAFE_STR(cf->name), g_strerror(errno), cf->fd); */
}
}
#endif
@ -83,11 +89,13 @@ liHandlerResult li_chunkfile_open(liVRequest *vr, liChunkFile *cf) {
* but needs to do io in case of FILE_CHUNK; the data is _not_ marked as "done"
* may return HANDLER_GO_ON, HANDLER_ERROR
*/
liHandlerResult li_chunkiter_read(liVRequest *vr, liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len) {
liHandlerResult li_chunkiter_read(liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len, GError **err) {
liChunk *c = li_chunkiter_chunk(iter);
off_t we_have, our_start;
liHandlerResult res = LI_HANDLER_GO_ON;
g_return_val_if_fail (err == NULL || *err == NULL, LI_HANDLER_ERROR);
if (!c) return LI_HANDLER_ERROR;
if (!data_start || !data_len) return LI_HANDLER_ERROR;
@ -106,7 +114,7 @@ liHandlerResult li_chunkiter_read(liVRequest *vr, liChunkIter iter, off_t start,
*data_len = length;
break;
case FILE_CHUNK:
if (LI_HANDLER_GO_ON != (res = li_chunkfile_open(vr, c->data.file.file))) return res;
if (LI_HANDLER_GO_ON != (res = li_chunkfile_open(c->data.file.file, err))) return res;
if (length > MAX_MMAP_CHUNK) length = MAX_MMAP_CHUNK;
@ -121,7 +129,7 @@ liHandlerResult li_chunkiter_read(liVRequest *vr, liChunkIter iter, off_t start,
read_chunk:
if (-1 == (we_have = pread(c->data.file.file->fd, c->mem->data, length, our_start))) {
if (EINTR == errno) goto read_chunk;
VR_ERROR(vr, "pread failed for '%s' (fd = %i): %s",
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkiter_read: pread failed for '%s' (fd = %i): %s",
GSTR_SAFE_STR(c->data.file.file->name), c->data.file.file->fd,
g_strerror(errno));
g_byte_array_free(c->mem, TRUE);
@ -131,7 +139,7 @@ read_chunk:
/* may return less than requested bytes due to signals */
/* CON_TRACE(srv, "read return unexpected number of bytes"); */
if (we_have == 0) {
VR_ERROR(vr, "pread returned 0 bytes for '%s' (fd = %i): unexpected end of file?",
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkiter_read: pread returned 0 bytes for '%s' (fd = %i): unexpected end of file?",
GSTR_SAFE_STR(c->data.file.file->name), c->data.file.file->fd);
g_byte_array_free(c->mem, TRUE);
c->mem = NULL;
@ -154,12 +162,14 @@ read_chunk:
/* same as li_chunkiter_read, but tries mmap() first and falls back to pread();
* as accessing mmap()-ed areas may result in SIGBUS, you have to handle that signal somehow.
*/
liHandlerResult li_chunkiter_read_mmap(liVRequest *vr, liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len) {
liHandlerResult li_chunkiter_read_mmap(liChunkIter iter, off_t start, off_t length, char **data_start, off_t *data_len, GError **err) {
liChunk *c = li_chunkiter_chunk(iter);
off_t we_want, we_have, our_start, our_offset;
liHandlerResult res = LI_HANDLER_GO_ON;
int mmap_errno = 0;
g_return_val_if_fail (err == NULL || *err == NULL, LI_HANDLER_ERROR);
if (!c) return LI_HANDLER_ERROR;
if (!data_start || !data_len) return LI_HANDLER_ERROR;
@ -178,7 +188,7 @@ liHandlerResult li_chunkiter_read_mmap(liVRequest *vr, liChunkIter iter, off_t s
*data_len = length;
break;
case FILE_CHUNK:
if (LI_HANDLER_GO_ON != (res = li_chunkfile_open(vr, c->data.file.file))) return res;
if (LI_HANDLER_GO_ON != (res = li_chunkfile_open(c->data.file.file, err))) return res;
if (length > MAX_MMAP_CHUNK) length = MAX_MMAP_CHUNK;
@ -217,11 +227,11 @@ read_chunk:
if (EINTR == errno) goto read_chunk;
/* prefer the error of the first syscall */
if (0 != mmap_errno) {
VR_ERROR(vr, "mmap failed for '%s' (fd = %i): %s",
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkiter_read_mmap: mmap failed for '%s' (fd = %i): %s",
GSTR_SAFE_STR(c->data.file.file->name), c->data.file.file->fd,
g_strerror(mmap_errno));
} else {
VR_ERROR(vr, "pread failed for '%s' (fd = %i): %s",
g_set_error(err, LI_CHUNK_ERROR, 0, "li_chunkiter_read_mmap: pread failed for '%s' (fd = %i): %s",
GSTR_SAFE_STR(c->data.file.file->name), c->data.file.file->fd,
g_strerror(errno));
}
@ -241,9 +251,11 @@ read_chunk:
/* don't advise files < 64Kb */
if (c->data.file.mmap.length > (64*1024) &&
0 != madvise(c->data.file.mmap.data, c->data.file.mmap.length, MADV_WILLNEED)) {
VR_ERROR(vr, "madvise failed for '%s' (fd = %i): %s",
/*
g_debug("madvise failed for '%s' (fd = %i): %s",
GSTR_SAFE_STR(c->data.file.file->name), c->data.file.file->fd,
g_strerror(errno));
*/
}
#endif
}
@ -270,24 +282,6 @@ static liChunk* chunk_new() {
return c;
}
/*
static void chunk_reset(chunk *c) {
if (!c) return;
c->type = UNUSED_CHUNK;
c->offset = 0;
if (c->data.str) g_string_free(c->data.str, TRUE);
c->data.str = NULL;
if (c->data.file.file) chunkfile_release(c->data.file.file);
c->data.file.file = NULL;
c->data.file.start = 0;
c->data.file.length = 0;
if (MAP_FAILED != c->data.file.mmap.data) munmap(c->data.file.mmap.data, c->data.file.mmap.length);
c->data.file.mmap.data = MAP_FAILED;
c->data.file.mmap.length = 0;
c->data.file.mmap.offset = 0;
}
*/
static void chunk_free(liChunkQueue *cq, liChunk *c) {
if (!c) return;
if (cq) {
@ -815,9 +809,12 @@ goffset li_chunkqueue_skip_all(liChunkQueue *cq) {
return bytes;
}
gboolean li_chunkqueue_extract_to(liVRequest *vr, liChunkQueue *cq, goffset len, GString *dest) {
gboolean li_chunkqueue_extract_to(liChunkQueue *cq, goffset len, GString *dest, GError **err) {
liChunkIter ci;
goffset coff, clen;
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
g_string_set_size(dest, 0);
if (len > cq->length) return FALSE;
@ -829,7 +826,7 @@ gboolean li_chunkqueue_extract_to(liVRequest *vr, liChunkQueue *cq, goffset len,
while (coff < clen) {
gchar *buf;
off_t we_have;
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, ci, coff, len, &buf, &we_have)) goto error;
if (LI_HANDLER_GO_ON != li_chunkiter_read(ci, coff, len, &buf, &we_have, err)) goto error;
g_string_append_len(dest, buf, we_have);
coff += we_have;
len -= we_have;
@ -845,9 +842,12 @@ error:
return FALSE;
}
gboolean li_chunkqueue_extract_to_bytearr(liVRequest *vr, liChunkQueue *cq, goffset len, GByteArray *dest) {
gboolean li_chunkqueue_extract_to_bytearr(liChunkQueue *cq, goffset len, GByteArray *dest, GError **err) {
liChunkIter ci;
goffset coff, clen;
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
g_byte_array_set_size(dest, 0);
if (len > cq->length) return FALSE;
@ -862,7 +862,7 @@ gboolean li_chunkqueue_extract_to_bytearr(liVRequest *vr, liChunkQueue *cq, goff
while (coff < clen) {
gchar *buf;
off_t we_have;
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, ci, coff, len, &buf, &we_have)) goto error;
if (LI_HANDLER_GO_ON != li_chunkiter_read(ci, coff, len, &buf, &we_have, err)) goto error;
g_byte_array_append(dest, (guint8*) buf, we_have);
coff += we_have;
len -= we_have;

18
src/main/chunk_parser.c

@ -22,10 +22,12 @@ liHandlerResult li_chunk_parser_prepare(liChunkParserCtx *ctx) {
return LI_HANDLER_GO_ON;
}
liHandlerResult li_chunk_parser_next(liVRequest *vr, liChunkParserCtx *ctx, char **p, char **pe) {
liHandlerResult li_chunk_parser_next(liChunkParserCtx *ctx, char **p, char **pe, GError **err) {
off_t l;
liHandlerResult res;
g_return_val_if_fail (err == NULL || *err == NULL, LI_HANDLER_ERROR);
if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;
while (ctx->start >= (l = li_chunkiter_length(ctx->curi))) {
@ -38,7 +40,7 @@ liHandlerResult li_chunk_parser_next(liVRequest *vr, liChunkParserCtx *ctx, char
if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(vr, ctx->curi, ctx->start, l - ctx->start, &ctx->buf, &ctx->length))) {
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(ctx->curi, ctx->start, l - ctx->start, &ctx->buf, &ctx->length, err))) {
return res;
}
@ -52,9 +54,11 @@ void li_chunk_parser_done(liChunkParserCtx *ctx, goffset len) {
ctx->start += len;
}
gboolean li_chunk_extract_to(liVRequest *vr, liChunkParserMark from, liChunkParserMark to, GString *dest) {
gboolean li_chunk_extract_to(liChunkParserMark from, liChunkParserMark to, GString *dest, GError **err) {
liChunkParserMark i;
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
g_string_set_size(dest, to.abs_pos - from.abs_pos);
li_g_string_clear(dest);
@ -63,7 +67,7 @@ gboolean li_chunk_extract_to(liVRequest *vr, liChunkParserMark from, liChunkPars
while (i.pos < len) {
char *buf;
off_t we_have;
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, i.ci, i.pos, len - i.pos, &buf, &we_have)) goto error;
if (LI_HANDLER_GO_ON != li_chunkiter_read(i.ci, i.pos, len - i.pos, &buf, &we_have, err)) goto error;
if (dest->len + we_have < dest->allocated_len) {
/* "fast" append */
memcpy(dest->str + dest->len, buf, we_have);
@ -79,7 +83,7 @@ gboolean li_chunk_extract_to(liVRequest *vr, liChunkParserMark from, liChunkPars
while (i.pos < to.pos) {
char *buf;
off_t we_have;
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, i.ci, i.pos, to.pos - i.pos, &buf, &we_have)) goto error;
if (LI_HANDLER_GO_ON != li_chunkiter_read(i.ci, i.pos, to.pos - i.pos, &buf, &we_have, err)) goto error;
if (dest->len + we_have < dest->allocated_len) {
/* "fast" append */
memcpy(dest->str + dest->len, buf, we_have);
@ -98,9 +102,9 @@ error:
return FALSE;
}
GString* li_chunk_extract(liVRequest *vr, liChunkParserMark from, liChunkParserMark to) {
GString* li_chunk_extract(liChunkParserMark from, liChunkParserMark to, GError **err) {
GString *str = g_string_sized_new(0);
if (li_chunk_extract_to(vr, from, to, str)) return str;
if (li_chunk_extract_to(from, to, str, err)) return str;
g_string_free(str, TRUE);
return NULL;
}

14
src/main/connection.c

@ -303,7 +303,12 @@ static G_GNUC_WARN_UNUSED_RESULT gboolean connection_try_read(liConnection *con)
if (con->srv_sock->read_cb) {
res = con->srv_sock->read_cb(con);
} else {
res = li_network_read(con->mainvr, con->sock_watcher.fd, con->raw_in, &con->raw_in_buffer);
GError *err = NULL;
res = li_network_read(con->sock_watcher.fd, con->raw_in, &con->raw_in_buffer, &err);
if (NULL != err) {
VR_ERROR(con->mainvr, "%s", err->message);
g_error_free(err);
}
}
if (NULL == con->wrk->network_read_buf && NULL != con->raw_in_buffer
@ -366,7 +371,12 @@ static G_GNUC_WARN_UNUSED_RESULT gboolean connection_try_write(liConnection *con
if (con->srv_sock->write_cb) {
res = con->srv_sock->write_cb(con, write_max);
} else {
res = li_network_write(con->mainvr, con->sock_watcher.fd, con->raw_out, write_max);
GError *err = NULL;
res = li_network_write(con->sock_watcher.fd, con->raw_out, write_max, &err);
if (NULL != err) {
VR_ERROR(con->mainvr, "%s", err->message);
g_error_free(err);
}
}
transferred = transferred - con->raw_out->length;

8
src/main/filter_buffer_on_disk.c

@ -68,6 +68,7 @@ liHandlerResult li_filter_buffer_on_disk(liVRequest *vr, liChunkQueue *out, liCh
liChunkIter ci;
off_t length, data_len;
char *data = NULL;
GError *err;
switch (c->type) {
case UNUSED_CHUNK: return LI_HANDLER_ERROR;
@ -86,7 +87,12 @@ liHandlerResult li_filter_buffer_on_disk(liVRequest *vr, liChunkQueue *out, liCh
length = li_chunk_length(c);
ci = li_chunkqueue_iter(in);
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, ci, 0, length, &data, &data_len)) {
err = NULL;
if (LI_HANDLER_GO_ON != li_chunkiter_read(ci, 0, length, &data, &data_len, &err)) {
if (NULL != err) {
VR_ERROR(vr, "%s", err->message);
g_error_free(err);
}
return LI_HANDLER_ERROR;
}

7
src/main/filter_chunked.c

@ -45,7 +45,12 @@ liHandlerResult li_filter_chunked_encode(liVRequest *vr, liChunkQueue *out, liCh
#define read_char(c) do { \
while (!p || p >= pe) { \
res = li_chunk_parser_next(vr, &ctx, &p, &pe); \
GError *err = NULL; \
res = li_chunk_parser_next(&ctx, &p, &pe, &err); \
if (NULL != err) { \
VR_ERROR(vr, "%s", err->message); \
g_error_free(err); \
} \
if (res == LI_HANDLER_WAIT_FOR_EVENT && in->is_closed) { \
res = LI_HANDLER_ERROR; \
} \

17
src/main/http_request_parser.rl

@ -5,10 +5,10 @@
/** Machine **/
#define _getString(M, FPC) (li_chunk_extract(vr, ctx->M, GETMARK(FPC)))
#define _getString(M, FPC) (li_chunk_extract(ctx->M, LI_GETMARK(FPC), NULL))
#define getString(FPC) _getString(mark, FPC)
#define _getStringTo(M, FPC, s) (li_chunk_extract_to(vr, ctx->M, GETMARK(FPC), s))
#define _getStringTo(M, FPC, s) (li_chunk_extract_to(ctx->M, LI_GETMARK(FPC), s, NULL))
#define getStringTo(FPC, s) _getStringTo(mark, FPC, s)
@ -17,7 +17,7 @@
machine li_http_request_parser;
variable cs ctx->chunk_ctx.cs;
action mark { ctx->mark = GETMARK(fpc); }
action mark { ctx->mark = LI_GETMARK(fpc); }
action done { fbreak; }
action method {
@ -149,8 +149,15 @@ liHandlerResult li_http_request_parse(liVRequest *vr, liHttpRequestCtx *ctx) {
while (!li_http_request_parser_has_error(ctx) && !li_http_request_parser_is_finished(ctx)) {
char *p, *pe;
if (LI_HANDLER_GO_ON != (res = li_chunk_parser_next(vr, &ctx->chunk_ctx, &p, &pe))) return res;
GError *err = NULL;
if (LI_HANDLER_GO_ON != (res = li_chunk_parser_next(&ctx->chunk_ctx, &p, &pe, &err))) {
if (NULL != err) {
VR_ERROR(vr, "%s", err->message);
g_error_free(err);
}
return res;
}
%% write exec;

17
src/main/http_response_parser.rl

@ -4,10 +4,12 @@
/** Machine **/
#define _getString(M, FPC) (li_chunk_extract(vr, ctx->M, GETMARK(FPC)))
#define _getString(M, FPC) (li_chunk_extract(ctx->M, LI_GETMARK(FPC), NULL))
#define getString(FPC) _getString(mark, FPC)
#define _getStringTo(M, FPC, s) (li_chunk_extract_to(vr, ctx->M, GETMARK(FPC), s))
#define _getStringTo(M, FPC, s) (li_chunk_extract_to(ctx->M, LI_GETMARK(FPC), s, NULL))
#define getStringTo(FPC, s) _getStringTo(mark, FPC, s)
@ -16,7 +18,7 @@
machine li_http_response_parser;
variable cs ctx->chunk_ctx.cs;
action mark { ctx->mark = GETMARK(fpc); }
action mark { ctx->mark = LI_GETMARK(fpc); }
action done { fbreak; }
action status {
@ -162,8 +164,15 @@ liHandlerResult li_http_response_parse(liVRequest *vr, liHttpResponseCtx *ctx) {
while (!li_http_response_parser_has_error(ctx)) {
char *p, *pe;
GError *err = NULL;
if (LI_HANDLER_GO_ON != (res = li_chunk_parser_next(vr, &ctx->chunk_ctx, &p, &pe))) return res;
if (LI_HANDLER_GO_ON != (res = li_chunk_parser_next(&ctx->chunk_ctx, &p, &pe, &err))) {
if (NULL != err) {
VR_ERROR(vr, "%s", err->message);
g_error_free(err);
}
return res;
}
%% write exec;

18
src/main/network.c

@ -2,6 +2,10 @@
#include <lighttpd/base.h>
#include <lighttpd/plugin_core.h>
GQuark li_network_error_quark(void) {
return g_quark_from_string("g-network-error-quark");
}
/** repeats write after EINTR */
ssize_t li_net_write(int fd, void *buf, ssize_t nbyte) {
ssize_t r;
@ -36,7 +40,7 @@ ssize_t li_net_read(int fd, void *buf, ssize_t nbyte) {
return r;
}
liNetworkStatus li_network_write(liVRequest *vr, int fd, liChunkQueue *cq, goffset write_max) {
liNetworkStatus li_network_write(int fd, liChunkQueue *cq, goffset write_max, GError **err) {
liNetworkStatus res;
#ifdef TCP_CORK
int corked = 0;
@ -54,9 +58,9 @@ liNetworkStatus li_network_write(liVRequest *vr, int fd, liChunkQueue *cq, goffs
/* TODO: add setup-option to select the backend */
#ifdef USE_SENDFILE
res = li_network_write_sendfile(vr, fd, cq, &write_max);
res = li_network_write_sendfile(fd, cq, &write_max, err);
#else
res = li_network_write_writev(vr, fd, cq, &write_max);
res = li_network_write_writev(fd, cq, &write_max, err);
#endif
#ifdef TCP_CORK
@ -69,7 +73,7 @@ liNetworkStatus li_network_write(liVRequest *vr, int fd, liChunkQueue *cq, goffs
return res;
}
liNetworkStatus li_network_read(liVRequest *vr, int fd, liChunkQueue *cq, liBuffer **buffer) {
liNetworkStatus li_network_read(int fd, liChunkQueue *cq, liBuffer **buffer, GError **err) {
const ssize_t blocksize = 16*1024; /* 16k */
off_t max_read = 16 * blocksize; /* 256k */
ssize_t r;
@ -79,8 +83,8 @@ liNetworkStatus li_network_read(liVRequest *vr, int fd, liChunkQueue *cq, liBuff
if (max_read > cq->limit->limit - cq->limit->current) {
max_read = cq->limit->limit - cq->limit->current;
if (max_read <= 0) {
max_read = 0; /* we still have to read something */
VR_ERROR(vr, "%s", "li_network_read: fd should be disabled as chunkqueue is already full");
g_set_error(err, LI_NETWORK_ERROR, 0, "li_network_read: fd should be disabled as chunkqueue is already full, aborting connection.");
return LI_NETWORK_STATUS_FATAL_ERROR;
}
}
}
@ -137,7 +141,7 @@ liNetworkStatus li_network_read(liVRequest *vr, int fd, liChunkQueue *cq, liBuff
case ETIMEDOUT:
return LI_NETWORK_STATUS_CONNECTION_CLOSE;
default:
VR_ERROR(vr, "oops, read from fd=%d failed: %s", fd, g_strerror(errno) );
g_set_error(err, LI_NETWORK_ERROR, 0, "li_network_read: oops, read from fd=%d failed: %s", fd, g_strerror(errno) );
return LI_NETWORK_STATUS_FATAL_ERROR;
}
} else if (0 == r) {

34
src/main/network_sendfile.c

@ -11,11 +11,11 @@ typedef enum {
NSR_FATAL_ERROR
} network_sendfile_result;
static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote);
static network_sendfile_result lighty_sendfile(int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote, GError **err);
#if defined(USE_LINUX_SENDFILE)
static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote) {
static network_sendfile_result lighty_sendfile(int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote, GError **err) {
ssize_t r;
off_t file_offset = offset;
@ -34,10 +34,9 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
break; /* try again */
case EINVAL:
case ENOSYS:
/* TODO: print a warning? */
return NSR_FALLBACK;
default:
VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "lighty_sendfile(linux): oops, write to fd=%d failed: %s", fd, g_strerror(errno));
return NSR_FATAL_ERROR;
}
}
@ -47,7 +46,7 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
#elif defined(USE_FREEBSD_SENDFILE)
static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote) {
static network_sendfile_result lighty_sendfile(int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote, GError **err) {
off_t r = 0;
while (-1 == sendfile(filefd, fd, offset, len, NULL, &r, 0)) {
@ -71,10 +70,9 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
case EINVAL:
case EOPNOTSUPP:
case ENOTSOCK:
/* TODO: print a warning? */
return NSR_FALLBACK;
default:
VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "lighty_sendfile(freebsd): oops, write to fd=%d failed: %s", fd, g_strerror(errno));
return NSR_FATAL_ERROR;
}
}
@ -84,7 +82,7 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
#elif defined(USE_SOLARIS_SENDFILEV)
static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote) {
static network_sendfile_result lighty_sendfile(int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote, GError **err) {
sendfilevec_t fvec;
fvec.sfv_fd = filefd;
@ -103,10 +101,9 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
break; /* try again */
case EAFNOSUPPORT:
case EPROTOTYPE:
/* TODO: print a warning? */
return NSR_FALLBACK;
default:
VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "lighty_sendfile(solaris): oops, write to fd=%d failed: %s", fd, g_strerror(errno));
return NSR_FATAL_ERROR;
}
}
@ -115,7 +112,7 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
#elif defined(USE_OSX_SENDFILE)
static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote) {
static network_sendfile_result lighty_sendfile(int fd, int filefd, goffset offset, ssize_t len, ssize_t *wrote, GError **err) {
off_t bytes = len;
while (-1 == sendfile(filefd, fd, offset, &bytes, NULL, 0)) {
@ -139,10 +136,9 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
case ENOTSUP:
case EOPNOTSUPP:
case ENOTSOCK:
/* TODO: print a warning? */
return NSR_FALLBACK;
default:
VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "lighty_sendfile(osx): oops, write to fd=%d failed: %s", fd, g_strerror(errno));
return NSR_FATAL_ERROR;
}
}
@ -155,7 +151,7 @@ static network_sendfile_result lighty_sendfile(liVRequest *vr, int fd, int filef
/* first chunk must be a FILE_CHUNK ! */
static liNetworkStatus network_backend_sendfile(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max) {
static liNetworkStatus network_backend_sendfile(int fd, liChunkQueue *cq, goffset *write_max, GError **err) {
off_t file_offset, toSend;
ssize_t r;
gboolean did_write_something = FALSE;
@ -171,7 +167,7 @@ static liNetworkStatus network_backend_sendfile(liVRequest *vr, int fd, liChunkQ
return did_write_something ? LI_NETWORK_STATUS_SUCCESS : LI_NETWORK_STATUS_FATAL_ERROR;
}
switch (li_chunkfile_open(vr, c->data.file.file)) {
switch (li_chunkfile_open(c->data.file.file, err)) {
case LI_HANDLER_GO_ON:
break;
default:
@ -183,7 +179,7 @@ static liNetworkStatus network_backend_sendfile(liVRequest *vr, int fd, liChunkQ
if (toSend > *write_max) toSend = *write_max;
r = 0;
switch (lighty_sendfile(vr, fd, c->data.file.file->fd, file_offset, toSend, &r)) {
switch (lighty_sendfile(fd, c->data.file.file->fd, file_offset, toSend, &r, err)) {
case NSR_SUCCESS:
li_chunkqueue_skip(cq, r);
*write_max -= r;
@ -202,13 +198,13 @@ static liNetworkStatus network_backend_sendfile(liVRequest *vr, int fd, liChunkQ
/* don't care about cached stat - file is open */
struct stat st;
if (-1 == fstat(fd, &st)) {
VR_ERROR(vr, "Couldn't fstat file: %s", g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "network_backend_sendfile: Couldn't fstat file: %s", g_strerror(errno));
return LI_NETWORK_STATUS_FATAL_ERROR;
}
if (file_offset > st.st_size) {
/* file shrinked, close the connection */
VR_ERROR(vr, "%s", "File shrinked, aborting");
g_set_error(err, LI_NETWORK_ERROR, 0, "network_backend_sendfile: File shrinked, aborting");
return LI_NETWORK_STATUS_FATAL_ERROR;
}
return LI_NETWORK_STATUS_WAIT_FOR_EVENT;
@ -222,7 +218,7 @@ static liNetworkStatus network_backend_sendfile(liVRequest *vr, int fd, liChunkQ
return LI_NETWORK_STATUS_SUCCESS;
}
liNetworkStatus li_network_write_sendfile(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max) {
liNetworkStatus li_network_write_sendfile(int fd, liChunkQueue *cq, goffset *write_max, GError **err) {
if (cq->length == 0) return LI_NETWORK_STATUS_FATAL_ERROR;
do {

6
src/main/network_write.c

@ -1,7 +1,7 @@
#include <lighttpd/base.h>
liNetworkStatus li_network_backend_write(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max) {
liNetworkStatus li_network_backend_write(int fd, liChunkQueue *cq, goffset *write_max, GError **err) {
const ssize_t blocksize = 16*1024; /* 16k */
char *block_data;
off_t block_len;
@ -14,7 +14,7 @@ liNetworkStatus li_network_backend_write(liVRequest *vr, int fd, liChunkQueue *c
return did_write_something ? LI_NETWORK_STATUS_SUCCESS : LI_NETWORK_STATUS_FATAL_ERROR;
ci = li_chunkqueue_iter(cq);
switch (li_chunkiter_read(vr, ci, 0, blocksize, &block_data, &block_len)) {
switch (li_chunkiter_read(ci, 0, blocksize, &block_data, &block_len, err)) {
case LI_HANDLER_GO_ON:
break;
case LI_HANDLER_ERROR:
@ -34,7 +34,7 @@ liNetworkStatus li_network_backend_write(liVRequest *vr, int fd, liChunkQueue *c
case ETIMEDOUT:
return LI_NETWORK_STATUS_CONNECTION_CLOSE;
default:
VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "li_network_backend_write: oops, write to fd=%d failed: %s", fd, g_strerror(errno));
return LI_NETWORK_STATUS_FATAL_ERROR;
}
} else if (0 == r) {

6
src/main/network_writev.c

@ -25,7 +25,7 @@
#endif
/* first chunk must be a STRING_CHUNK ! */
liNetworkStatus li_network_backend_writev(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max) {
liNetworkStatus li_network_backend_writev(int fd, liChunkQueue *cq, goffset *write_max, GError **err) {
off_t we_have;
ssize_t r;
gboolean did_write_something = FALSE;
@ -83,7 +83,7 @@ liNetworkStatus li_network_backend_writev(liVRequest *vr, int fd, liChunkQueue *
case EINTR:
break; /* try again */
default:
VR_ERROR(vr, "oops, write to fd=%d failed: %s", fd, g_strerror(errno));
g_set_error(err, LI_NETWORK_ERROR, 0, "li_network_backend_writev: oops, write to fd=%d failed: %s", fd, g_strerror(errno));
goto cleanup;
}
}
@ -115,7 +115,7 @@ cleanup:
return res;
}
liNetworkStatus li_network_write_writev(liVRequest *vr, int fd, liChunkQueue *cq, goffset *write_max) {
liNetworkStatus li_network_write_writev(int fd, liChunkQueue *cq, goffset *write_max, GError **err) {
if (cq->length == 0) return LI_NETWORK_STATUS_FATAL_ERROR;
do {
switch (li_chunkqueue_first_chunk(cq)->type) {

10
src/modules/mod_cache_disk_etag.c

@ -153,6 +153,7 @@ static liHandlerResult cache_etag_filter_miss(liVRequest *vr, liFilter *f) {
gchar *buf;
off_t buflen;
liChunkIter citer = li_chunkqueue_iter(f->in);
GError *err = NULL;
UNUSED(vr);
if (0 == f->in->length) return LI_HANDLER_GO_ON;
@ -163,8 +164,13 @@ static liHandlerResult cache_etag_filter_miss(liVRequest *vr, liFilter *f) {
return LI_HANDLER_GO_ON;
}
if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, citer, 0, 64*1024, &buf, &buflen)) {
VR_ERROR(vr, "%s", "Couldn't read data from chunkqueue");
if (LI_HANDLER_GO_ON != li_chunkiter_read(citer, 0, 64*1024, &buf, &buflen, &err)) {
if (NULL != err) {
VR_ERROR(vr, "Couldn't read data from chunkqueue: %s", err->message);
g_error_free(err);
} else {
VR_ERROR(vr, "%s", "Couldn't read data from chunkqueue");
}
cache_etag_file_free(cfile);
f->param = NULL;
li_chunkqueue_steal_all(f->out, f->in);

16
src/modules/mod_deflate.c

@ -217,13 +217,19 @@ static liHandlerResult deflate_filter_zlib(liVRequest *vr, liFilter *f) {
char *data;
off_t len;
liChunkIter ci;
GError *err = NULL;
if (0 == f->in->length) break;
ci = li_chunkqueue_iter(f->in);
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(vr, ci, 0, blocksize, &data, &len)))
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(ci, 0, blocksize, &data, &len, &err))) {
if (NULL != err) {
VR_ERROR(vr, "Couldn't read data from chunkqueue: %s", err->message);
g_error_free(err);
}
return res;
}
if (ctx->is_gzip) {
ctx->crc = crc32(ctx->crc, (unsigned char*) data, len);
@ -406,13 +412,19 @@ static liHandlerResult deflate_filter_bzip2(liVRequest *vr, liFilter *f) {
char *data;
off_t len;
liChunkIter ci;
GError *err = NULL;
if (0 == f->in->length) break;
ci = li_chunkqueue_iter(f->in);
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(vr, ci, 0, blocksize, &data, &len)))
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(ci, 0, blocksize, &data, &len, &err))) {
if (NULL != err) {
VR_ERROR(vr, "Couldn't read data from chunkqueue: %s", err->message);
g_error_free(err);
}
return res;
}
bz->next_in = data;
bz->avail_in = len;

24
src/modules/mod_fastcgi.c

@ -479,7 +479,7 @@ static gboolean fastcgi_get_packet(fastcgi_connection *fcon) {
}
}
if (!li_chunkqueue_extract_to_bytearr(fcon->vr, fcon->fcgi_in, FCGI_HEADER_LEN, fcon->buf_in_record)) return FALSE; /* need more data */
if (!li_chunkqueue_extract_to_bytearr(fcon->fcgi_in, FCGI_HEADER_LEN, fcon->buf_in_record, NULL)) return FALSE; /* need more data */
data = (const unsigned char*) fcon->buf_in_record->data;
fcon->fcgi_in_record.version = data[0];
@ -531,7 +531,7 @@ static gboolean fastcgi_parse_response(fastcgi_connection *fcon) {
break;
case FCGI_STDERR:
len = fastcgi_available(fcon);
li_chunkqueue_extract_to(vr, fcon->fcgi_in, len, vr->wrk->tmp_str);
li_chunkqueue_extract_to(fcon->fcgi_in, len, vr->wrk->tmp_str, NULL);
if (OPTION(FASTCGI_OPTION_LOG_PLAIN_ERRORS).boolean) {
li_log_split_lines(vr->wrk->srv, vr->wrk, li_log_vr_map(vr), LI_LOG_LEVEL_BACKEND, 0, vr->wrk->tmp_str->str, "");
} else {
@ -567,11 +567,17 @@ static void fastcgi_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
if (fcon->fcgi_in->is_closed) {
li_ev_io_rem_events(loop, w, EV_READ);
} else {
switch (li_network_read(fcon->vr, w->fd, fcon->fcgi_in, &fcon->fcgi_in_buffer)) {
GError *err = NULL;
switch (li_network_read(w->fd, fcon->fcgi_in, &fcon->fcgi_in_buffer, &err)) {
case LI_NETWORK_STATUS_SUCCESS:
break;
case LI_NETWORK_STATUS_FATAL_ERROR:
VR_ERROR(fcon->vr, "(%s) network read fatal error", fcon->ctx->socket_str->str);
if (NULL != err) {
VR_ERROR(fcon->vr, "(%s) network read fatal error: %s", fcon->ctx->socket_str->str, err->message);
g_error_free(err);
} else {
VR_ERROR(fcon->vr, "(%s) network read fatal error", fcon->ctx->socket_str->str);
}
li_vrequest_error(fcon->vr);
return;
case LI_NETWORK_STATUS_CONNECTION_CLOSE:
@ -589,11 +595,17 @@ static void fastcgi_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
if (fcon->fd != -1 && (revents & EV_WRITE)) {
if (fcon->fcgi_out->length > 0) {
switch (li_network_write(fcon->vr, w->fd, fcon->fcgi_out, 256*1024)) {
GError *err = NULL;
switch (li_network_write(w->fd, fcon->fcgi_out, 256*1024, &err)) {
case LI_NETWORK_STATUS_SUCCESS:
break;
case LI_NETWORK_STATUS_FATAL_ERROR:
VR_ERROR(fcon->vr, "(%s) network write fatal error", fcon->ctx->socket_str->str);
if (NULL != err) {
VR_ERROR(fcon->vr, "(%s) network write fatal error: %s", fcon->ctx->socket_str->str, err->message);
g_error_free(err);
} else {
VR_ERROR(fcon->vr, "(%s) network write fatal error", fcon->ctx->socket_str->str);
}
li_vrequest_error(fcon->vr);
return;
case LI_NETWORK_STATUS_CONNECTION_CLOSE:

10
src/modules/mod_gnutls.c

@ -272,6 +272,7 @@ static liNetworkStatus mod_gnutls_con_write(liConnection *con, goffset write_max
liChunkIter ci;
liChunkQueue *cq = con->raw_out;
mod_connection_ctx *conctx = con->srv_sock_data;
GError *err = NULL;
if (!conctx->initial_handshaked_finished) {
liNetworkStatus res = mod_gnutls_do_handshake(con, conctx);
@ -279,14 +280,19 @@ static liNetworkStatus mod_gnutls_con_write(liConnection *con, goffset write_max
}
do {
if (0 == cq->length)
if (0 == cq->length) {
return LI_NETWORK_STATUS_SUCCESS;
}
ci = li_chunkqueue_iter(cq);
switch (li_chunkiter_read(con->mainvr, ci, 0, blocksize, &block_data, &block_len)) {
switch (li_chunkiter_read(ci, 0, blocksize, &block_data, &block_len, &err)) {
case LI_HANDLER_GO_ON:
break;
case LI_HANDLER_ERROR:
if (NULL != err) {
VR_ERROR(con->mainvr, "Couldn't read data from chunkqueue: %s", err->message);
g_error_free(err);
}
default:
return LI_NETWORK_STATUS_FATAL_ERROR;
}

8
src/modules/mod_memcached.c

@ -451,13 +451,19 @@ static liHandlerResult memcache_store_filter(liVRequest *vr, liFilter *f) {
off_t len;
liChunkIter ci;
liHandlerResult res;
GError *err = NULL;
if (0 == f->in->length) break;
ci = li_chunkqueue_iter(f->in);
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(vr, ci, 0, 16*1024, &data, &len)))
if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(ci, 0, 16*1024, &data, &len, &err))) {
if (NULL != err) {
VR_ERROR(vr, "Couldn't read data from chunkqueue: %s", err->message);
g_error_free(err);
}
return res;
}
if ((gssize) (len + mf->buf->used) > (gssize) mf->ctx->maxsize) {
/* response too big, switch to "forward" mode */

11
src/modules/mod_openssl.c

@ -293,14 +293,21 @@ static liNetworkStatus openssl_con_write(liConnection *con, goffset write_max) {
}
do {
if (0 == cq->length)
GError *err = NULL;
if (0 == cq->length) {
return LI_NETWORK_STATUS_SUCCESS;
}
ci = li_chunkqueue_iter(cq);
switch (li_chunkiter_read(con->mainvr, ci, 0, blocksize, &block_data, &block_len)) {
switch (li_chunkiter_read(ci, 0, blocksize, &block_data, &block_len, &err)) {
case LI_HANDLER_GO_ON:
break;
case LI_HANDLER_ERROR:
if (NULL != err) {
VR_ERROR(con->mainvr, "Couldn't read data from chunkqueue: %s", err->message);
g_error_free(err);
}
default:
return LI_NETWORK_STATUS_FATAL_ERROR;
}

20
src/modules/mod_proxy.c

@ -228,11 +228,17 @@ static void proxy_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
if (pcon->proxy_in->is_closed) {
li_ev_io_rem_events(loop, w, EV_READ);
} else {
switch (li_network_read(pcon->vr, w->fd, pcon->proxy_in, &pcon->proxy_in_buffer)) {
GError *err = NULL;
switch (li_network_read(w->fd, pcon->proxy_in, &pcon->proxy_in_buffer, &err)) {
case LI_NETWORK_STATUS_SUCCESS:
break;
case LI_NETWORK_STATUS_FATAL_ERROR:
VR_ERROR(pcon->vr, "(%s) network read fatal error", pcon->ctx->socket_str->str);
if (NULL != err) {
VR_ERROR(pcon->vr, "(%s) network read fatal error: %s", pcon->ctx->socket_str->str, err->message);
g_error_free(err);
} else {
VR_ERROR(pcon->vr, "(%s) network read fatal error", pcon->ctx->socket_str->str);
}
li_vrequest_error(pcon->vr);
return;
case LI_NETWORK_STATUS_CONNECTION_CLOSE:
@ -250,11 +256,17 @@ static void proxy_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
if (pcon->fd != -1 && (revents & EV_WRITE)) {
if (pcon->proxy_out->length > 0) {
switch (li_network_write(pcon->vr, w->fd, pcon->proxy_out, 256*1024)) {
GError *err = NULL;
switch (li_network_write(w->fd, pcon->proxy_out, 256*1024, &err)) {
case LI_NETWORK_STATUS_SUCCESS:
break;
case LI_NETWORK_STATUS_FATAL_ERROR:
VR_ERROR(pcon->vr, "(%s) network write fatal error", pcon->ctx->socket_str->str);
if (NULL != err) {
VR_ERROR(pcon->vr, "(%s) network write fatal error: %s", pcon->ctx->socket_str->str, err->message);
g_error_free(err);
} else {
VR_ERROR(pcon->vr, "(%s) network write fatal error", pcon->ctx->socket_str->str);
}
li_vrequest_error(pcon->vr);
return;
case LI_NETWORK_STATUS_CONNECTION_CLOSE:

20
src/modules/mod_scgi.c

@ -331,11 +331,17 @@ static void scgi_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
if (scon->scgi_in->is_closed) {
li_ev_io_rem_events(loop, w, EV_READ);
} else {
switch (li_network_read(scon->vr, w->fd, scon->scgi_in, &scon->scgi_in_buffer)) {
GError *err = NULL;
switch (li_network_read(w->fd, scon->scgi_in, &scon->scgi_in_buffer, &err)) {
case LI_NETWORK_STATUS_SUCCESS:
break;
case LI_NETWORK_STATUS_FATAL_ERROR:
VR_ERROR(scon->vr, "(%s) network read fatal error", scon->ctx->socket_str->str);
if (NULL != err) {
VR_ERROR(scon->vr, "(%s) network read fatal error: %s", scon->ctx->socket_str->str, err->message);
g_error_free(err);
} else {
VR_ERROR(scon->vr, "(%s) network read fatal error", scon->ctx->socket_str->str);
}
li_vrequest_error(scon->vr);
return;
case LI_NETWORK_STATUS_CONNECTION_CLOSE:
@ -353,11 +359,17 @@ static void scgi_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
if (scon->fd != -1 && (revents & EV_WRITE)) {
if (scon->scgi_out->length > 0) {
switch (li_network_write(scon->vr, w->fd, scon->scgi_out, 256*1024)) {
GError *err = NULL;
switch (li_network_write(w->fd, scon->scgi_out, 256*1024, &err)) {
case LI_NETWORK_STATUS_SUCCESS:
break;
case LI_NETWORK_STATUS_FATAL_ERROR:
VR_ERROR(scon->vr, "(%s) network write fatal error", scon->ctx->socket_str->str);
if (NULL != err) {
VR_ERROR(scon->vr, "(%s) network write fatal error: %s", scon->ctx->socket_str->str, err->message);
g_error_free(err);
} else {
VR_ERROR(scon->vr, "(%s) network write fatal error", scon->ctx->socket_str->str);
}
li_vrequest_error(scon->vr);
return;
case LI_NETWORK_STATUS_CONNECTION_CLOSE:

2
src/unittests/test-chunk.c

@ -18,7 +18,7 @@ static void cq_load_str(liChunkQueue *cq, const gchar *s, size_t len) {
static void cq_assert_eq(liChunkQueue *cq, const gchar *s, size_t len) {
GString *buf = g_string_sized_new(cq->length);
g_assert(li_chunkqueue_extract_to(NULL, cq, cq->length, buf));
g_assert(li_chunkqueue_extract_to(cq, cq->length, buf, NULL));
g_assert(0 == memcmp(s, buf->str, len));
g_string_free(buf, TRUE);
}

Loading…
Cancel
Save