Basic ragel suport
parent
3c05dca97a
commit
503e8d7859
|
@ -0,0 +1,19 @@
|
|||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# Thomas Nagy, 2006 (ita)
|
||||
|
||||
"Ragel: '.rl' files are converted into .c files using 'ragel': {.rl -> .c -> .o}"
|
||||
|
||||
import TaskGen
|
||||
|
||||
TaskGen.declare_chain(
|
||||
name = 'ragel',
|
||||
action = '${RAGEL} -o ${TGT} ${SRC}',
|
||||
ext_in = '.rl',
|
||||
ext_out = '.c',
|
||||
before = 'c',
|
||||
)
|
||||
|
||||
def detect(conf):
|
||||
dang = conf.find_program('ragel', var='RAGEL')
|
||||
if not dang: conf.fatal('cannot find the program "ragel"')
|
29
src/chunks.c
29
src/chunks.c
|
@ -179,6 +179,35 @@ read_chunk:
|
|||
return HANDLER_GO_ON;
|
||||
}
|
||||
|
||||
GString* chunk_extract(server *srv, connection *con, chunk_parser_mark from, chunk_parser_mark to) {
|
||||
GString *str = g_string_sized_new(0);
|
||||
chunk_parser_mark i;
|
||||
for ( i = from; i.ci.element != to.ci.element; chunkiter_next(&i.ci) ) {
|
||||
goffset len = chunkiter_length(i.ci);
|
||||
while (i.pos < len) {
|
||||
char *buf;
|
||||
off_t we_have;
|
||||
if (HANDLER_GO_ON != chunkiter_read(srv, con, i.ci, i.pos, len - i.pos, &buf, &we_have)) goto error;
|
||||
g_string_append_len(str, buf, we_have);
|
||||
i.pos += we_have;
|
||||
}
|
||||
i.pos = 0;
|
||||
}
|
||||
while (i.pos < to.pos) {
|
||||
char *buf;
|
||||
off_t we_have;
|
||||
if (HANDLER_GO_ON != chunkiter_read(srv, con, i.ci, i.pos, to.pos - i.pos, &buf, &we_have)) goto error;
|
||||
g_string_append_len(str, buf, we_have);
|
||||
i.pos += we_have;
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
error:
|
||||
g_string_free(str, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************
|
||||
* chunk *
|
||||
******************/
|
||||
|
|
42
src/chunks.h
42
src/chunks.h
|
@ -15,6 +15,9 @@ typedef struct chunkqueue chunkqueue;
|
|||
struct chunkiter;
|
||||
typedef struct chunkiter chunkiter;
|
||||
|
||||
struct chunk_parser_mark;
|
||||
typedef struct chunk_parser_mark chunk_parser_mark;
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/* Open a file only once, so it shouldn't get lost;
|
||||
|
@ -66,6 +69,11 @@ struct chunkiter {
|
|||
GList *element;
|
||||
};
|
||||
|
||||
struct chunk_parser_mark {
|
||||
chunkiter ci;
|
||||
off_t pos;
|
||||
};
|
||||
|
||||
/******************
|
||||
* chunkfile *
|
||||
******************/
|
||||
|
@ -73,7 +81,7 @@ struct chunkiter {
|
|||
/* open the file cf->name if it is not already opened for reading
|
||||
* may return HANDLER_GO_ON, HANDLER_ERROR, HANDLER_WAIT_FOR_FD
|
||||
*/
|
||||
handler_t chunkfile_open(server *srv, connection *con, chunkfile *cf);
|
||||
LI_API handler_t chunkfile_open(server *srv, connection *con, chunkfile *cf);
|
||||
|
||||
/******************
|
||||
* chunk iterator *
|
||||
|
@ -89,7 +97,9 @@ INLINE goffset chunkiter_length(chunkiter iter);
|
|||
* the data is _not_ marked as "done"
|
||||
* may return HANDLER_GO_ON, HANDLER_ERROR, HANDLER_WAIT_FOR_FD
|
||||
*/
|
||||
handler_t chunkiter_read(server *srv, connection *con, chunkiter iter, off_t start, off_t length, char **data_start, off_t *data_len);
|
||||
LI_API handler_t chunkiter_read(server *srv, connection *con, chunkiter iter, off_t start, off_t length, char **data_start, off_t *data_len);
|
||||
|
||||
LI_API GString* chunk_extract(server *srv, connection *con, chunk_parser_mark from, chunk_parser_mark to);
|
||||
|
||||
/******************
|
||||
* chunk *
|
||||
|
@ -101,44 +111,44 @@ INLINE goffset chunk_length(chunk *c);
|
|||
* chunkqueue *
|
||||
******************/
|
||||
|
||||
chunkqueue* chunkqueue_new();
|
||||
void chunkqueue_reset(chunkqueue *cq);
|
||||
void chunkqueue_free(chunkqueue *cq);
|
||||
LI_API chunkqueue* chunkqueue_new();
|
||||
LI_API void chunkqueue_reset(chunkqueue *cq);
|
||||
LI_API void chunkqueue_free(chunkqueue *cq);
|
||||
|
||||
/* pass ownership of str to chunkqueue, do not free/modify it afterwards
|
||||
* you may modify the data (not the length) if you are sure it isn't sent before.
|
||||
*/
|
||||
void chunkqueue_append_string(chunkqueue *cq, GString *str);
|
||||
LI_API void chunkqueue_append_string(chunkqueue *cq, GString *str);
|
||||
|
||||
/* memory gets copied */
|
||||
void chunkqueue_append_mem(chunkqueue *cq, void *mem, gssize len);
|
||||
LI_API void chunkqueue_append_mem(chunkqueue *cq, void *mem, gssize len);
|
||||
|
||||
/* pass ownership of filename, do not free it */
|
||||
void chunkqueue_append_file(chunkqueue *cq, GString *filename, off_t start, off_t length);
|
||||
LI_API void chunkqueue_append_file(chunkqueue *cq, GString *filename, off_t start, off_t length);
|
||||
/* if you already opened the file, you can pass the fd here - do not close it */
|
||||
void chunkqueue_append_file_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd);
|
||||
LI_API void chunkqueue_append_file_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd);
|
||||
|
||||
/* temp files get deleted after usage */
|
||||
/* pass ownership of filename, do not free it */
|
||||
void chunkqueue_append_tempfile(chunkqueue *cq, GString *filename, off_t start, off_t length);
|
||||
LI_API void chunkqueue_append_tempfile(chunkqueue *cq, GString *filename, off_t start, off_t length);
|
||||
/* if you already opened the file, you can pass the fd here - do not close it */
|
||||
void chunkqueue_append_tempfile_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd);
|
||||
LI_API void chunkqueue_append_tempfile_fd(chunkqueue *cq, GString *filename, off_t start, off_t length, int fd);
|
||||
|
||||
|
||||
/* steal up to length bytes from in and put them into out, return number of bytes stolen */
|
||||
goffset chunkqueue_steal_len(chunkqueue *out, chunkqueue *in, goffset length);
|
||||
LI_API goffset chunkqueue_steal_len(chunkqueue *out, chunkqueue *in, goffset length);
|
||||
|
||||
/* steal all chunks from in and put them into out, return number of bytes stolen */
|
||||
goffset chunkqueue_steal_all(chunkqueue *out, chunkqueue *in);
|
||||
LI_API goffset chunkqueue_steal_all(chunkqueue *out, chunkqueue *in);
|
||||
|
||||
/* steal the first chunk from in and append it to out, return number of bytes stolen */
|
||||
goffset chunkqueue_steal_chunk(chunkqueue *out, chunkqueue *in);
|
||||
LI_API goffset chunkqueue_steal_chunk(chunkqueue *out, chunkqueue *in);
|
||||
|
||||
/* skip up to length bytes in a chunkqueue, return number of bytes skipped */
|
||||
goffset chunkqueue_skip(chunkqueue *cq, goffset length);
|
||||
LI_API goffset chunkqueue_skip(chunkqueue *cq, goffset length);
|
||||
|
||||
/* skip all chunks in a queue (similar to reset, but keeps stats) */
|
||||
goffset chunkqueue_skip_all(chunkqueue *cq);
|
||||
LI_API goffset chunkqueue_skip_all(chunkqueue *cq);
|
||||
|
||||
/* if the chunk an iterator refers gets stolen/skipped/...,
|
||||
* the iterator isn't valid anymore
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _LIGHTTPD_HTTP_REQUEST_PARSER_H_
|
||||
#define _LIGHTTPD_HTTP_REQUEST_PARSER_H_
|
||||
|
||||
struct http_request_ctx;
|
||||
typedef struct http_request_ctx http_request_ctx;
|
||||
|
||||
#include "chunks.h"
|
||||
|
||||
struct http_request_ctx {
|
||||
chunkqueue *cq;
|
||||
|
||||
goffset bytes_in;
|
||||
|
||||
/* current position
|
||||
* buf is curi[start..start+length)
|
||||
*/
|
||||
chunkiter curi;
|
||||
off_t start, length;
|
||||
char *buf;
|
||||
|
||||
int cs;
|
||||
|
||||
chunk_parser_mark mark;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
#include "http_request_parser.h"
|
||||
|
||||
static chunk_parser_mark getmark(http_request_ctx *ctx, const char *fpc) {
|
||||
chunk_parser_mark m;
|
||||
m.ci = ctx->curi;
|
||||
m.pos = ctx->start + fpc - ctx->buf;
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Machine **/
|
||||
|
||||
%%{
|
||||
|
||||
machine http_request_parser;
|
||||
|
||||
CRLF = "\r\n";
|
||||
|
||||
action mark { ctx->mark = getmark(ctx, fpc); }
|
||||
|
||||
main := CRLF ;
|
||||
}%%
|
||||
|
||||
%% write data;
|
||||
|
||||
void http_request_parse(server *srv, connection *con, http_request_ctx *ctx) {
|
||||
int cs = ctx->cs;
|
||||
while (cs != http_request_parser_error && cs != http_request_parser_first_final) {
|
||||
char *p, *pe;
|
||||
off_t l;
|
||||
|
||||
l = chunkiter_length(ctx->curi);
|
||||
if (ctx->start >= l) {
|
||||
chunkiter_next(&ctx->curi);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (HANDLER_GO_ON != chunkiter_read(srv, con, ctx->curi, ctx->start, l - ctx->start, &ctx->buf, &ctx->length)) {
|
||||
return;
|
||||
}
|
||||
|
||||
p = ctx->buf;
|
||||
pe = ctx->buf + ctx->length;
|
||||
|
||||
%% write exec;
|
||||
|
||||
ctx->start += pe - p;
|
||||
ctx->bytes_in += pe - p;
|
||||
if (ctx->start >= l) {
|
||||
chunkiter_next(&ctx->curi);
|
||||
ctx->start = 0;
|
||||
}
|
||||
}
|
||||
ctx->cs = cs;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
#import Action, Object, Params, os, sys
|
||||
#import Object, Params, os, sys
|
||||
import Params
|
||||
|
||||
common_uselib = 'glib '
|
||||
|
@ -11,6 +11,7 @@ common_source='''
|
|||
base.c
|
||||
chunks.c
|
||||
condition.c
|
||||
http_request_parser.rl
|
||||
log.c
|
||||
options.c
|
||||
sys-files.c
|
||||
|
@ -76,7 +77,7 @@ def build(bld):
|
|||
main.name = 'lighttpd'
|
||||
main.source = common_source + main_source
|
||||
main.target='lighttpd' + env['APPEND']
|
||||
main.uselib += 'lighty dl openssl pcre lua glib ' + common_uselib
|
||||
main.uselib += 'lighty dl openssl pcre lua ' + common_uselib
|
||||
|
||||
#lighty_mod(bld, 'mod_access', 'mod_access.c')
|
||||
#lighty_mod(bld, 'mod_alias', 'mod_alias.c')
|
||||
|
|
4
wscript
4
wscript
|
@ -13,7 +13,10 @@ blddir = 'build'
|
|||
|
||||
def set_options(opt):
|
||||
# the gcc module provides a --debug-level option
|
||||
|
||||
opt.tool_options('compiler_cc')
|
||||
opt.tool_options('ragel', tooldir = '.')
|
||||
|
||||
#opt.add_option('--with-xattr', action='store_true', help='xattr-support for the stat-cache [default: off]', dest='xattr', default = False)
|
||||
#opt.add_option('--with-mysql', action='store_true', help='with mysql-support for the mod_sql_vhost [default: off]', dest = 'mysql', default = False)
|
||||
#opt.add_option('--with-postgresql', action='store_true', help='with postgress-support for the mod_sql_vhost [default: off]', dest = 'postgresql', default = False)
|
||||
|
@ -191,6 +194,7 @@ def configure(conf):
|
|||
opts = Params.g_options
|
||||
|
||||
conf.check_tool('compiler_cc')
|
||||
conf.check_tool('ragel', tooldir = '.')
|
||||
|
||||
if not opts.libdir:
|
||||
opts.libdir = opts.prefix + "/lib/lighttpd" + opts.append
|
||||
|
|
Loading…
Reference in New Issue