Basic ragel suport

personal/stbuehler/wip
Stefan Bühler 14 years ago
parent 3c05dca97a
commit 503e8d7859
  1. 19
      ragel.py
  2. 29
      src/chunks.c
  3. 42
      src/chunks.h
  4. 26
      src/http_request_parser.h
  5. 55
      src/http_request_parser.rl
  6. 5
      src/wscript
  7. 4
      wscript

@ -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"')

@ -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 *
******************/

@ -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')

@ -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…
Cancel
Save