Merge branch 'master' into websockets

master
Nicolas Favre-Felix 13 years ago
commit da8c888f88

@ -32,7 +32,7 @@ INSTALL_DIRS = $(DESTDIR) \
all: $(OUT) Makefile all: $(OUT) Makefile
$(OUT): $(OBJS) Makefile $(OUT): $(OBJS) Makefile
$(CC) $(LDFLAGS) -o $(OUT) $(OBJS) $(CC) -o $(OUT) $(OBJS) $(LDFLAGS)
%.o: %.c %.h Makefile %.o: %.c %.h Makefile
$(CC) -c $(CFLAGS) -o $@ $< $(CC) -c $(CFLAGS) -o $@ $<

@ -180,7 +180,7 @@ http_client_on_message_complete(struct http_parser *p) {
} }
c->http_version = c->parser.http_minor; c->http_version = c->parser.http_minor;
if(p->upgrade) { /* WebSocket, don't execute just yet */ if(p->upgrade && c->w->s->cfg->websockets) { /* WebSocket, don't execute just yet */
c->is_websocket = 1; c->is_websocket = 1;
return 0; return 0;
} }

@ -282,7 +282,7 @@ cmd_select_format(struct http_client *client, struct cmd *cmd,
{.s = "jpg", .sz = 3, .f = custom_type_reply, .ct = "image/jpeg"}, {.s = "jpg", .sz = 3, .f = custom_type_reply, .ct = "image/jpeg"},
{.s = "jpeg", .sz = 4, .f = custom_type_reply, .ct = "image/jpeg"}, {.s = "jpeg", .sz = 4, .f = custom_type_reply, .ct = "image/jpeg"},
{.s = "js", .sz = 2, .f = custom_type_reply, .ct = "application/javascript"}, {.s = "js", .sz = 2, .f = json_reply, .ct = "application/javascript"},
{.s = "css", .sz = 3, .f = custom_type_reply, .ct = "text/css"}, {.s = "css", .sz = 3, .f = custom_type_reply, .ct = "text/css"},
}; };

@ -83,6 +83,8 @@ conf_read(const char *filename) {
else conf->verbosity = (log_level)tmp; else conf->verbosity = (log_level)tmp;
} else if(strcmp(json_object_iter_key(kv), "daemonize") == 0 && json_typeof(jtmp) == JSON_TRUE) { } else if(strcmp(json_object_iter_key(kv), "daemonize") == 0 && json_typeof(jtmp) == JSON_TRUE) {
conf->daemonize = 1; conf->daemonize = 1;
} else if(strcmp(json_object_iter_key(kv), "websockets") == 0 && json_typeof(jtmp) == JSON_TRUE) {
conf->websockets = 1;
} else if(strcmp(json_object_iter_key(kv), "database") == 0 && json_typeof(jtmp) == JSON_INTEGER) { } else if(strcmp(json_object_iter_key(kv), "database") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
conf->database = json_integer_value(jtmp); conf->database = json_integer_value(jtmp);
} else if(strcmp(json_object_iter_key(kv), "pool_size") == 0 && json_typeof(jtmp) == JSON_INTEGER) { } else if(strcmp(json_object_iter_key(kv), "pool_size") == 0 && json_typeof(jtmp) == JSON_INTEGER) {

@ -22,6 +22,9 @@ struct conf {
/* daemonize process, off by default */ /* daemonize process, off by default */
int daemonize; int daemonize;
/* WebSocket support, off by default */
int websockets;
/* database number */ /* database number */
int database; int database;

@ -78,11 +78,12 @@ format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content
http_response_set_header(resp, "Content-Type", ct); http_response_set_header(resp, "Content-Type", ct);
http_response_set_keep_alive(resp, 1); http_response_set_keep_alive(resp, 1);
http_response_set_header(resp, "Transfer-Encoding", "chunked"); http_response_set_header(resp, "Transfer-Encoding", "chunked");
http_response_set_body(resp, p, sz);
http_response_write(resp, cmd->fd); http_response_write(resp, cmd->fd);
} } else {
/* Asynchronous chunk write. */ /* Asynchronous chunk write. */
http_response_write_chunk(cmd->fd, cmd->w, p, sz); http_response_write_chunk(cmd->fd, cmd->w, p, sz);
}
} else { } else {
/* compute ETag */ /* compute ETag */

@ -19,6 +19,7 @@ http_response_init(struct worker *w, int code, const char *msg) {
r->code = code; r->code = code;
r->msg = msg; r->msg = msg;
r->w = w; r->w = w;
r->keep_alive = 0; /* default */
http_response_set_header(r, "Server", "Webdis"); http_response_set_header(r, "Server", "Webdis");
@ -131,13 +132,31 @@ http_schedule_write(int fd, struct http_response *r) {
} }
static char *
format_chunk(const char *p, size_t sz, size_t *out_sz) {
char *out, tmp[64];
int chunk_size;
/* calculate format size */
chunk_size = sprintf(tmp, "%x\r\n", (int)sz);
*out_sz = chunk_size + sz + 2;
out = malloc(*out_sz);
memcpy(out, tmp, chunk_size);
memcpy(out + chunk_size, p, sz);
memcpy(out + chunk_size + sz, "\r\n", 2);
return out;
}
void void
http_response_write(struct http_response *r, int fd) { http_response_write(struct http_response *r, int fd) {
char *p; char *p;
int i, ret; int i, ret;
r->keep_alive = 0; /*r->keep_alive = 0;*/
r->out_sz = sizeof("HTTP/1.x xxx ")-1 + strlen(r->msg) + 2; r->out_sz = sizeof("HTTP/1.x xxx ")-1 + strlen(r->msg) + 2;
r->out = calloc(r->out_sz + 1, 1); r->out = calloc(r->out_sz + 1, 1);
@ -145,13 +164,15 @@ http_response_write(struct http_response *r, int fd) {
(void)ret; (void)ret;
p = r->out; p = r->out;
if(!r->chunked) {
if(r->code == 200 && r->body) { if(r->code == 200 && r->body) {
char content_length[10]; char content_length[10];
sprintf(content_length, "%zd", r->body_len); sprintf(content_length, "%zd", r->body_len);
http_response_set_header(r, "Content-Length", content_length); http_response_set_header(r, "Content-Length", content_length);
} else if(!r->chunked) { } else {
http_response_set_header(r, "Content-Length", "0"); http_response_set_header(r, "Content-Length", "0");
} }
}
for(i = 0; i < r->header_count; ++i) { for(i = 0; i < r->header_count; ++i) {
/* "Key: Value\r\n" */ /* "Key: Value\r\n" */
@ -190,9 +211,20 @@ http_response_write(struct http_response *r, int fd) {
/* append body if there is one. */ /* append body if there is one. */
if(r->body && r->body_len) { if(r->body && r->body_len) {
r->out = realloc(r->out, r->out_sz + r->body_len);
memcpy(r->out + r->out_sz, r->body, r->body_len); char *tmp = (char*)r->body;
r->out_sz += r->body_len; size_t tmp_len = r->body_len;
if(r->chunked) { /* replace body with formatted chunk */
tmp = format_chunk(r->body, r->body_len, &tmp_len);
}
r->out = realloc(r->out, r->out_sz + tmp_len);
memcpy(r->out + r->out_sz, tmp, tmp_len);
r->out_sz += tmp_len;
if(r->chunked) { /* need to free the chunk */
free(tmp);
}
} }
/* send buffer to client */ /* send buffer to client */
@ -245,6 +277,7 @@ http_send_error(struct http_client *c, short code, const char *msg) {
*/ */
void void
http_response_set_keep_alive(struct http_response *r, int enabled) { http_response_set_keep_alive(struct http_response *r, int enabled) {
r->keep_alive = enabled;
if(enabled) { if(enabled) {
http_response_set_header(r, "Connection", "Keep-Alive"); http_response_set_header(r, "Connection", "Keep-Alive");
} else { } else {
@ -273,25 +306,13 @@ http_send_options(struct http_client *c) {
void void
http_response_write_chunk(int fd, struct worker *w, const char *p, size_t sz) { http_response_write_chunk(int fd, struct worker *w, const char *p, size_t sz) {
char *out, tmp[64];
size_t out_sz;
int chunk_size;
struct http_response *r = http_response_init(w, 0, NULL); struct http_response *r = http_response_init(w, 0, NULL);
r->keep_alive = 1; /* chunks are always keep-alive */
/* calculate format size */ /* format packet */
chunk_size = sprintf(tmp, "%x\r\n", (int)sz); r->out = format_chunk(p, sz, &r->out_sz);
out_sz = chunk_size + sz + 2;
out = malloc(out_sz);
memcpy(out, tmp, chunk_size);
memcpy(out + chunk_size, p, sz);
memcpy(out + chunk_size + sz, "\r\n", 2);
/* send async write */ /* send async write */
r->out = out;
r->out_sz = out_sz;
http_schedule_write(fd, r); http_schedule_write(fd, r);
} }

@ -145,6 +145,10 @@ int
server_start(struct server *s) { server_start(struct server *s) {
int i; int i;
/* initialize libevent */
s->base = event_base_new();
if(s->cfg->daemonize) { if(s->cfg->daemonize) {
server_daemonize(); server_daemonize();
@ -172,9 +176,6 @@ server_start(struct server *s) {
return -1; return -1;
} }
/* initialize libevent */
s->base = event_base_new();
/* start http server */ /* start http server */
event_set(&s->ev, s->fd, EV_READ | EV_PERSIST, server_can_accept, s); event_set(&s->ev, s->fd, EV_READ | EV_PERSIST, server_can_accept, s);
event_base_set(s->base, &s->ev); event_base_set(s->base, &s->ev);

@ -9,6 +9,7 @@
"threads": 3, "threads": 3,
"daemonize": false, "daemonize": false,
"websockets": false,
"database": 0, "database": 0,

Loading…
Cancel
Save