aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--handler.c48
-rw-r--r--handler.h10
-rw-r--r--http.c21
-rw-r--r--http.h2
5 files changed, 64 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index e29c8ac..fc00b3a 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,8 @@
CC = cc # c99 (default value) does not allow POSIX extensions.
PROJECT = slcl
O = -Og
-CFLAGS = $(O) -g -Wall -Idynstr/include -MD -MF -
+CDEFS = -D_FILE_OFFSET_BITS=64 # Required for large file support on 32-bit.
+CFLAGS = $(O) $(CDEFS) -g -Wall -Idynstr/include -MD -MF -
LIBS = -lcjson -lssl -lm -lcrypto
LDFLAGS = $(LIBS)
DEPS = $(OBJECTS:.o=.d)
diff --git a/handler.c b/handler.c
index 6a3d626..05650ca 100644
--- a/handler.c
+++ b/handler.c
@@ -10,15 +10,14 @@
struct handler
{
- const char *tmpdir;
-
- struct handler_cfg
+ struct handler_cfg cfg;
+ struct elem
{
char *url;
enum http_op op;
handler_fn f;
void *user;
- } *cfg;
+ } *elem;
struct server *server;
struct client
@@ -96,10 +95,10 @@ static int on_payload(const struct http_payload *const p,
for (size_t i = 0; i < h->n_cfg; i++)
{
- const struct handler_cfg *const cfg = &h->cfg[i];
+ const struct elem *const e = &h->elem[i];
- if (cfg->op == p->op && !wildcard_cmp(p->resource, cfg->url))
- return cfg->f(p, r, cfg->user);
+ if (e->op == p->op && !wildcard_cmp(p->resource, e->url))
+ return e->f(p, r, e->user);
}
fprintf(stderr, "Not found: %s\n", p->resource);
@@ -112,6 +111,18 @@ static int on_payload(const struct http_payload *const p,
return 0;
}
+static int on_length(const unsigned long long len,
+ const struct http_cookie *const c, void *const user)
+{
+ struct client *const cl = user;
+ struct handler *const h = cl->h;
+
+ if (h->cfg.length)
+ return h->cfg.length(len, c, h->cfg.user);
+
+ return 0;
+}
+
static struct client *find_or_alloc_client(struct handler *const h,
struct server_client *const c)
{
@@ -134,8 +145,9 @@ static struct client *find_or_alloc_client(struct handler *const h,
.read = on_read,
.write = on_write,
.payload = on_payload,
+ .length = on_length,
.user = ret,
- .tmpdir = h->tmpdir
+ .tmpdir = h->cfg.tmpdir
};
*ret = (const struct client)
@@ -282,9 +294,9 @@ void handler_free(struct handler *const h)
if (h)
{
for (size_t i = 0; i < h->n_cfg; i++)
- free(h->cfg[i].url);
+ free(h->elem[i].url);
- free(h->cfg);
+ free(h->elem);
free_clients(h);
server_close(h->server);
}
@@ -292,7 +304,7 @@ void handler_free(struct handler *const h)
free(h);
}
-struct handler *handler_alloc(const char *const tmpdir)
+struct handler *handler_alloc(const struct handler_cfg *const cfg)
{
struct handler *const h = malloc(sizeof *h);
@@ -303,7 +315,7 @@ struct handler *handler_alloc(const char *const tmpdir)
return NULL;
}
- *h = (const struct handler){.tmpdir = tmpdir};
+ *h = (const struct handler){.cfg = *cfg};
return h;
}
@@ -311,17 +323,17 @@ int handler_add(struct handler *const h, const char *url,
const enum http_op op, const handler_fn f, void *const user)
{
const size_t n = h->n_cfg + 1;
- struct handler_cfg *const cfgs = realloc(h->cfg, n * sizeof *h->cfg);
+ struct elem *const elem = realloc(h->elem, n * sizeof *h->elem);
- if (!cfgs)
+ if (!elem)
{
fprintf(stderr, "%s: realloc(3): %s\n", __func__, strerror(errno));
return -1;
}
- struct handler_cfg *const c = &cfgs[h->n_cfg];
+ struct elem *const e = &elem[h->n_cfg];
- *c = (const struct handler_cfg)
+ *e = (const struct elem)
{
.url = strdup(url),
.op = op,
@@ -329,13 +341,13 @@ int handler_add(struct handler *const h, const char *url,
.user = user
};
- if (!c->url)
+ if (!e->url)
{
fprintf(stderr, "%s: strdup(3): %s\n", __func__, strerror(errno));
return -1;
}
- h->cfg = cfgs;
+ h->elem = elem;
h->n_cfg = n;
return 0;
}
diff --git a/handler.h b/handler.h
index 69f8cbf..d851f65 100644
--- a/handler.h
+++ b/handler.h
@@ -7,7 +7,15 @@
typedef int (*handler_fn)(const struct http_payload *p,
struct http_response *r, void *user);
-struct handler *handler_alloc(const char *tmpdir);
+struct handler_cfg
+{
+ const char *tmpdir;
+ int (*length)(unsigned long long len, const struct http_cookie *c,
+ void *user);
+ void *user;
+};
+
+struct handler *handler_alloc(const struct handler_cfg *cfg);
void handler_free(struct handler *h);
int handler_add(struct handler *h, const char *url, enum http_op op,
handler_fn f, void *user);
diff --git a/http.c b/http.c
index 5c4626b..a06f29d 100644
--- a/http.c
+++ b/http.c
@@ -797,6 +797,18 @@ static int process_header(struct http_ctx *const h, const char *const line,
return 0;
}
+static int check_length(struct http_ctx *const h)
+{
+ struct ctx *const c = &h->ctx;
+ const struct http_cookie cookie =
+ {
+ .field = c->field,
+ .value = c->value
+ };
+
+ return h->cfg.length(c->post.len, &cookie, h->cfg.user);
+}
+
static int header_cr_line(struct http_ctx *const h)
{
const char *const line = (const char *)h->line;
@@ -810,11 +822,20 @@ static int header_cr_line(struct http_ctx *const h)
return payload_get(h, line);
case HTTP_OP_POST:
+ {
if (!c->post.len)
return payload_post(h, line);
+ else if (c->boundary)
+ {
+ const int res = check_length(h);
+
+ if (res)
+ return res;
+ }
c->state = BODY_LINE;
return 0;
+ }
}
}
diff --git a/http.h b/http.h
index 3390e49..33f42c6 100644
--- a/http.h
+++ b/http.h
@@ -79,6 +79,8 @@ struct http_cfg
int (*write)(const void *buf, size_t n, void *user);
int (*payload)(const struct http_payload *p, struct http_response *r,
void *user);
+ int (*length)(unsigned long long len, const struct http_cookie *c,
+ void *user);
const char *tmpdir;
void *user;
};