[chunk/network] use glib error system to report errors (instead of using virtualrequest context)
parent
77f786ed18
commit
b1c45e6a8f
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; \
|
||||
} \
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|